(BC 一周年) hdu 5312 Sequence

Sequence

Accepts: 25

Submissions: 1442

Time Limit: 2000/2000 MS (Java/Others)

Memory Limit: 262144/262144 K (Java/Others)

问题描述

Soda习得了一个数列, 数列的第nn (n \ge 1)(n≥1)项是3n(n-1)+13n(n−1)+1. 现在他想知道对于一个给定的整数mm, 是否可以表示成若干项上述数列的和. 如果可以, 那么需要的最小项数是多少?

例如, 22可以表示为7+7+7+17+7+7+1, 也可以表示为19+1+1+119+1+1+1.

输入描述

输入有多组数据. 第一行有一个整数TT (1 \le T \le 10^4)(1≤T≤10?4??), 表示测试数据组数. 然后对于每组数据:

一行包含1个整数 mm (1 \le m \le 10^9)(1≤m≤10?9??).

输出描述

对于每组数据输出最小花费.

输入样例

10
1
2
3
4
5
6
7
8
22
10

输出样例

1
2
3
4
5
6
1
2
4
4

比赛的时候没做出来.这道题需要用到的一个重要的性质是,任意一个自然数可以表示成至多三个三角形数(1,3,6,10,15.....)的和(orz高斯)然后也有推广到任意自然数可以表示成k个k角形数的和的结论(费马提出了猜想,柯西给了证明)然后官方题解说的比较好:

这个题看上去是一个贪心, 但是这个贪心显然是错的. 事实上这道题目很简单, 先判断1个是否可以, 然后判断2个是否可以. 之后找到最小的k (k > 2)k(k>2), 使得(m - k) mod 6 = 0(m−k)mod6=0即可.

证明如下: 3n(n-1)+1 = 6(n*(n-1)/2)+13n(n−1)+1=6(n∗(n−1)/2)+1, 注意到n*(n-1)/2n∗(n−1)/2是三角形数, 任意一个自然数最多只需要3个三角形数即可表示. 枚举需要kk个, 那么显然m=6(km=6(k个三角形数的和)+k)+k, 由于k \ge 3k≥3, 只要m-km−k是6的倍数就一定是有解的.

事实上, 打个表应该也能发现规律.

另外还有一点,特判一个和两个的情况时,一个的好判断,扫一遍就好了

两个的话,由于这个数列是递增的,我们可以从两边往中间,算是一个不错的优化,具体见代码.

/*************************************************************************
    > File Name: code/nv/#ann/1003.cpp
    > Author: 111qqz
    > Email: [email protected]
    > Created Time: 2015年07月28日 星期二 23时03分09秒
 ************************************************************************/

#include<iostream>
#include<iomanip>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<map>
#include<set>
#include<queue>
#include<vector>
#include<stack>
#define y0 abc111qqz
#define y1 hust111qqz
#define yn hez111qqz
#define j1 cute111qqz
#define tm crazy111qqz
#define lr dying111qqz
using namespace std;
#define REP(i, n) for (int i=0;i<int(n);++i)
typedef long long LL;
typedef unsigned long long ULL;
const int inf = 0x7fffffff;
const int N=1E5+7;
int k,m,f[N];
void init()
{
    for ( int i = 1 ; i <N; i++)
    {
    f[i]=3*i*(i-1)+1;
    if (f[i]>1000000000)
    {
        k = i-1;
        break;
    }
    }
}
int solve (int x)
{
    for ( int i = 1 ; f[i]<=x ; i++ )
    {
    if (x==f[i])
        return 1;
    }
    int j = k;
    for ( int i = 1 ; i <= k-1&&f[i]<x ; i++)     //因为数列递增,所以可以这样写.
    {
    while(f[i]+f[j]>x) j--;
    if (f[i]+f[j]==x) return 2;
    }
    for ( int i = 3 ; i <= m ; i++ )
    {
    if ((m-i)%6==0)
        return i;
    }
}
int main()
{
    int T;
    init();
    cin>>T;
    int ans;
    while (T--)
    {

    scanf("%d",&m);
    cout<<solve(m)<<endl;

    }

    return 0;
}
时间: 2024-10-29 19:06:04

(BC 一周年) hdu 5312 Sequence的相关文章

hdu 5312 Sequence(数学推导——三角形数)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5312 Sequence Time Limit: 2000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) Total Submission(s): 1336    Accepted Submission(s): 410 Problem Description Today, Soda has learned a

(BC 一周年)hdu 5311 Hidden String

Hidden String Accepts: 437 Submissions: 2174 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others) 问题描述 今天是BestCoder一周年纪念日. 比赛管理员Soda有一个长度为nn的字符串ss. 他想要知道能否找到ss的三个互不相交的子串s[l_1..r_1]s[l?1??..r?1??], s[l_2..r_2]s[l?2??..r?2

hdu 5312 Sequence【数学推导】

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5312 解法: 这个题看上去是一个贪心, 但是这个贪心显然是错的. 事实上这道题目很简单, 先判断1个是否可以, 然后判断2个是否可以. 之后找到最小的整数k (k > 2), 使得(m - k) mod 6 = 0即可. 证明如下: 3n(n-1)+1 = 6(n*(n-1)/2)+1, 注意到n*(n-1)/2是三角形数, 任意一个自然数最多只需要3个三角形数即可表示. 枚举需要k个. 事实上,

hdu 5312 Sequence(数学推导+线性探查(两数相加版))

Problem Description Today, Soda has learned a sequence whose n-th (n≥1) item is 3n(n−1)+1. Now he wants to know if an integer m can be represented as the sum of some items of that sequence. If possible, what are the minimum items needed? For example,

HDU 5312 Sequence(三角形数应用)——BestCoder 1st Anniversary ($)

传送门 Sequence Time Limit: 2000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 1424    Accepted Submission(s): 442 Problem Description Today, Soda has learned a sequence whose n-th (n≥1) item is 3n(n?1)+1. Now

HDU 5312 Sequence (规律题)

题意:一个序列的第n项为3*n*(n-1)+1,而 n>=1,现在给一个正整数m,问其最少由多少个序列中的数组成? 思路:首先,序列第1项是1,所以任何数都能构成了.但是最少应该是多少?对式子进行变形,6*(n*(n-1)/2)+1,看到了三角形数n*(n-1)/2,那么应该是6*(任意自然数)+x=m才对,因为最多只要3个三角形数就能组成任何自然数啦. 不妨试试m%6是多少?这样试图求x可以吗?因为任意自然数最多由3个组成,如果是k个,那么应该x>=k,别忘了还有个+1的项.x-k那部分,就

hdu 5312 Sequence(数学思维)

题意:通式为3*i*(i-1)+1(n>=1)的数列中每个数可用若干次,求构成给定n所需的最小个数: 思路: 设构成n所需个数为x,则n=3*1*(1-1)+3*2*(2-1)+...+3*x*(x-1)+x;当时推到这一步就没有再做下去了: 然后整理得n=6*(sigma((i*(i-1)/2))+x(i*(i-1)为偶数); 也就是说n%6即为所求结果,当n%6=1,2时特判一下是否能找到满足条件的数: 二分查找:(手动二分)(STL二分) #include<cstdio> #inc

hdu 5312 Sequence 三角形数

这道题可以用三角形数的性质解出来,所谓三角形数就是n*(n-1)/2其中n>2.就是1,3,6,10--,也可以表示为 n*(n+1)/2...性质:任何一个正整数最多用三个三角形数就可以表示出来,这道题是3*n*(n-1)+1,就可以 表示为6*(n*(n-1)/2)+1,假如m需要k(k>=3)个数来表示,就相当于6*(k个三角形数的和)+k = m:所以 只要判断(m-k)%6是否等于0就可以了.需要一个或两个数的时候需要特判一下.通过这道题了解了三角形数的这个神性质 贴代码: #inc

HDU 3397 Sequence operation(线段树)

HDU 3397 Sequence operation 题目链接 题意:给定一个01序列,有5种操作 0 a b [a.b]区间置为0 1 a b [a,b]区间置为1 2 a b [a,b]区间0变成1,1变成0 3 a b 查询[a,b]区间1的个数 4 a b 查询[a,b]区间连续1最长的长度 思路:线段树线段合并.须要两个延迟标记一个置为01,一个翻转,然后因为4操作,须要记录左边最长0.1.右边最长0.1,区间最长0.1,然后区间合并去搞就可以 代码: #include <cstdi