题目链接:
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 ", ++cases, (a[n] + 2) % 10007); 24 } 25 return 0; 26 }