本原串
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1091 Accepted Submission(s): 350
Problem Description
由0和1组成的串中,不能表示为由几个相同的较小的串连接成的串,称为本原串,有多少个长为n(n<=100000000)的本原串?
答案mod2008.
例如,100100不是本原串,因为他是由两个100组成,而1101是本原串。
答案mod2008.
例如,100100不是本原串,因为他是由两个100组成,而1101是本原串。
Input
输入包括多个数据,每个数据一行,包括一个整数n,代表串的长度。
Output
对于每个测试数据,输出一行,代表有多少个符合要求本原串,答案mod2008.
Sample Input
1
2
3
4
Sample Output
2
2
6
12
F[n]=2^n-F[k],k为n的约数。
此题用反面情况求解,长度为n的串有2^n中,减去非本原串,非本原串肯定是由长度为v字串不断重复u次得到的,那么v必然是n的约数。
感觉很长时间没做题了脑袋笨了不少,约数枚举法忘了。不然肯定超时
1 #include <cstring> 2 #include <iostream> 3 #include <cstdio> 4 #include <algorithm> 5 #include <map> 6 using namespace std; 7 typedef long long LL; 8 map<int,int> m; 9 map<int,int>::iterator ite; 10 LL n,ans; 11 LL mod_pow(LL x,LL n,int mod) 12 { 13 LL res=1; 14 while(n) 15 { 16 if(n&1) 17 res=res*x%mod; 18 x=x*x%mod; 19 n>>=1; 20 } 21 return res; 22 } 23 int cal(LL n) 24 { 25 int i,j; 26 if(m[n]!=0) 27 return m[n]; 28 m[n]=mod_pow(2,n,2008)-2; 29 for(i=2;i*i<=n;i++) 30 { 31 if(n%i==0) 32 { 33 m[n]=(m[n]-cal(i)+2008)%2008; //不然可能是负数 34 if(i*i!=n) 35 m[n]=(m[n]-cal(n/i)+2008)%2008; 36 37 } 38 } 39 return m[n]; 40 } 41 int main() 42 { 43 m[0]=0; 44 m[1]=2; 45 m[2]=2; 46 //freopen("in.txt","r",stdin); 47 while(scanf("%d",&n)!=EOF) 48 { 49 if(n<=2) 50 printf("%d ",m[n]); 51 else 52 { 53 m[n]=cal(n); 54 printf("%d ",m[n]); 55 } 56 } 57 }