Codeforces 900D Unusual Sequences:记忆化搜索
題目鏈接:http://codeforces.com/problemset/problem/900/D
題意:
給定x,y,問你有多少個數(shù)列a滿足gcd(a[i]) = x 且 ∑(a[i]) = y。
?
題解:
由于gcd(a[i]) = x,所以y一定是x的倍數(shù),否則無解。
那么原題就等價于:問你有多少個數(shù)列a滿足gcd(a[i]) = 1 且 ∑(a[i]) = y/x。
?
設(shè)f(k)為gcd(a[i]) = 1 且 ∑(a[i]) = k時的答案。
只滿足條件∑(a[i]) = k的數(shù)列共有2^(k-1)種(隔板法)
然后要從中去掉gcd不為1的數(shù)列。
每個和為k且gcd不為1的數(shù)列a1,對應(yīng)著一個和為k的因數(shù)且gcd為1的數(shù)列a2。
因為a1可以由a2整體放大而來。
那么也就是f(k) = 2^(k-1) - ∑ f(p),其中p為k的因數(shù)(p != k)。
搜索 + map記憶化即可。
?
由于需要用到的f(k),k均為y/x的因數(shù),最多sqrt(y/x)個。
加上map的log復(fù)雜度,所以總復(fù)雜度為O(sqrt(n)*log(n))。
?
AC Code:
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <map> 5 #define MOD 1000000007 6 7 using namespace std; 8 9 int x,y; 10 map<int,int> mp; 11 12 long long quick_pow(long long n,long long k) 13 { 14 long long ans=1; 15 while(k>0) 16 { 17 if(k&1) ans=(ans*n)%MOD; 18 n=n*n%MOD; 19 k>>=1; 20 } 21 return ans; 22 } 23 24 long long dfs(int i) 25 { 26 if(i==1) return 1; 27 if(mp.count(i)) return mp[i]; 28 long long ans=quick_pow(2,i-1); 29 for(int j=2;j*j<=i;j++) 30 { 31 if(i%j==0) 32 { 33 ans=((ans-dfs(j))%MOD+MOD)%MOD; 34 if(i/j!=j) ans=((ans-dfs(i/j))%MOD+MOD)%MOD; 35 } 36 } 37 ans=((ans-1)%MOD+MOD)%MOD; 38 return mp[i]=ans; 39 } 40 41 int main() 42 { 43 cin>>x>>y; 44 cout<<(y%x==0 ? dfs(y/x) : 0)<<endl; 45 }
?
轉(zhuǎn)載于:https://www.cnblogs.com/Leohh/p/8464069.html
總結(jié)
以上是生活随笔為你收集整理的Codeforces 900D Unusual Sequences:记忆化搜索的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 求一个八字伤感短句个性签名。
- 下一篇: 求水星记歌词!