hdu-3524 Perfect Squares---打表+找规律+循环节

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=3524

题目大意:

求i^2 mod 2^n有多少可能

解题思路:

先打表,求出n较小的时候的数据

n 1 2 3 4 5 6 7 8 9 10 11 12 13
答案 2 2 3 4 7 12 23 44 87 127 343 684 1367

发现差值分别是 0 1 1 3 5 11 21 43 85 171 341 683,

规律是后一项是前一项的两倍减一或者两倍加一,一开始发现这个规律准备从这里着手,但是还是求不出第n项

第n项就等于2+上述差值的第n-1项前缀和(因为差值是从第二项开始的)

上述差值的前缀和为 0 1 2 5 10 21 42 85 170 341 682

比如n = 3,ans[3] = 2 + 1,1就是第2项前缀和

n = 5, ans[5] = 2 + 5 = 7,5就是第3项前缀和

然后会发现前缀和有规律,后一项是前一项的两倍或者两倍+1,按照这个规律,可以暴力出前缀和+2就是答案,直接打表模上10007,求出10万项先看看

发现ans[10007] = ans[1] = 2     ans[10008] = ans[2] = 2     ans[10009] = ans[3] = 3,之后的每一项都是这样

找到循环节

那么直接求出前10006项即可,对于n直接模上10006即可,注意模上10006之后会出现等于0的情况,可以将ans[0] = ans[10006],也可以通过特殊的取模运算。

对于n 求n - 1 % 10006 + 1,那么就是他的对应项数,10006对应着就是10006,10007 对应 1

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int a[10010];
 4 int main()
 5 {
 6     a[1] = 0;a[2] = 0;
 7     int v = 1;
 8     for(int i = 3; i <= 10006; i++)
 9     {
10         a[i] = a[i - 1] * 2 + v;
11         v = !v;
12         a[i] %= 10007;
13         //cout<<i<<" "<<a[i]<<endl;
14     }
15     int n;
16     int T, cases = 0;
17     cin >> T;
18     while(T--)
19     {
20         //将n模上10006转化到10006上面
21         cin >> n;
22         n = (n - 1) % 10006 + 1;
23         printf("Case #%d: %d\n", ++cases, (a[n] + 2) % 10007);
24     }
25     return 0;
26 }

 

posted @ 2018-05-15 16:55  _努力努力再努力x  阅读(312)  评论(0编辑  收藏  举报