BestCoder 1st Anniversary($) 1003 Sequence

题目传送门

 1 /*
 2    官方题解:
 3    这个题看上去是一个贪心, 但是这个贪心显然是错的.
 4    事实上这道题目很简单, 先判断1个是否可以, 然后判断2个是否可以. 之后找到最小的k(k>2), 使得(m-k)mod6=0即可.
 5    证明如下:
 6    3n(n-1)+1=6(n*(n-1)/2)+1, 注意到n*(n-1)/2是三角形数, 任意一个自然数最多只需要3个三角形数即可表示. 
 7    枚举需要k个, 那么显然m=6(k个三角形数的和)+k, 由于k≥3, 只要m?k是6的倍数就一定是有解的.
 8    事实上, 打个表应该也能发现规律.
 9  */
10 #include <cstdio>
11 #include <algorithm>
12 #include <cmath>
13 #include <cstring>
14 using namespace std;
15 
16 typedef long long ll;
17 const int MAXN = 2e4 + 10;
18 const int INF = 0x3f3f3f3f;
19 ll a[MAXN];
20 int tot;
21 
22 void solve(void)    {
23     for (ll i=1; i<=20000; ++i)    {
24         a[i] = (ll) 3 * i * (i - 1) + 1;
25         if (a[i] > (ll) 1000000000) return ;
26         tot = i;
27     }
28 }
29 
30 bool ok(ll m)   {
31     int j = tot;
32     for (int i=1; i<=tot; ++i)  {
33         while (a[i] + a[j] > m) j--;
34         if (j >=1 && a[i] + a[j] == m)  return true;
35     }
36     return false;
37 }
38 
39 int main(void)  {       //BestCoder 1st Anniversary($) 1003 Sequence
40     //freopen ("C.in", "r", stdin);
41     tot = 0;    solve ();
42     int T;  scanf ("%d", &T);
43     while (T--) {
44         ll m;   scanf ("%I64d", &m);
45         if (m % 6 == 0) puts ("6");
46         else if (m % 6 == 1)    {
47             if (*lower_bound (a+1, a+1+tot, m) == m)    puts ("1");
48             else    puts ("7");
49         }
50         else if (m % 6 == 2)    {
51             if (ok (m)) puts ("2");
52             else    puts ("8");
53         }
54         else    printf ("%d
", m % 6);
55     }
56 
57     return 0;
58 }
编译人生,运行世界!
原文地址:https://www.cnblogs.com/Running-Time/p/4677125.html