HDU 2197 本原串 快速冪取模+遞推
阿新 • • 發佈:2018-12-24
Problem Description
由0和1組成的串中,不能表示為由幾個相同的較小的串連線成的串,稱為本原串,有多少個長為n(n<=100000000)的本原串?
答案mod2008.
例如,100100不是本原串,因為他是由兩個100組成,而1101是本原串。
Input
輸入包括多個數據,每個資料一行,包括一個整數n,代表串的長度。
Output
對於每個測試資料,輸出一行,代表有多少個符合要求本原串,答案mod2008.
Sample Input
1
2
3
4
Sample Output
2
2
6
12
程式碼及註釋如下:
/* 此題是求本元串的個數.... 長度為n的由0,1組成的字串一共有2^n個. 所以只要求出不是本元串的個數就可以了... 一開始以為此題只與素因子有關,但是想到8的時候發現並不是... 百度了一波題解,發現原來有遞推關係.... 遞推關係為: len[n]=2^n-len[x]. x為n的因子.... */ #include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <map> using namespace std; int n; map<int,int>ma; int fastpow (int a,int b) { int sum=1; while (b>0) { if(b&1) sum=sum*a%2008; b>>=1; a=a*a%2008; } return sum; } int Div (int x) { if(x==1) return 2; if(ma.find(x)!=ma.end()) return ma[x]; int sum=fastpow(2,x); for (int i=2;i*i<=x;i++) { if(x%i==0) { sum=(sum-Div(i)+2008)%2008; if(i*i!=x) sum=(sum-Div(x/i)+2008)%2008; } } return ma[x]=(sum+2006)%2008; } int main() { while (scanf("%d",&n)!=EOF) { printf("%d\n",Div(n)); } return 0; }