http://acm.hdu.edu.cn/showproblem.php?pid=2197
本原串
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1483 Accepted Submission(s): 507
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
Author
scnu
代码:
#include<bits/stdc++.h>
#define debug cout<<"aaa"<<endl
#define mem(a,b) memset(a,b,sizeof(a))
#define LL long long
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define MIN_INT (-2147483647-1)
#define MAX_INT 2147483647
#define MAX_LL 9223372036854775807i64
#define MIN_LL (-9223372036854775807i64-1)
using namespace std;
const int N = 100000000 + 5;
const int mod = 2008;
int f[N],n;
int quick(int a,int b){
int ans=1;
a%=mod;
while(b){
if(b&1){
ans=(ans*a)%mod;
}
b>>=1;
a=(a*a)%mod;
}
return ans;
}
int getf(int x){
if(f[x]) return f[x];//记忆化搜索
if(x==1) return f[x]=2;//搜索终点
int ans=quick(2,x)-2;
ans%=mod;
for(int i=2;i*i<=x;i++){//枚举因子,不能从因子1开始,不然会造成n/i=n的死循环
if(x%i==0){
ans-=getf(i);
if(i*i!=x){
ans-=getf(x/i);
}
ans%=mod;
}
}
return f[x]=(ans+mod)%mod;
}
int main(){
while(~scanf("%d",&n)){
printf("%d\n",getf(n));
}
return 0;
}