問有多少個這樣的數字序列ios
全部數的GCD等於x 而且 全部數的和等於yc++
題解:ide
很是難有思路啊 看題解後過的。spa
考慮序列GCD爲x的倍數 即GCD = n*x 和固然都爲y 這個條件不要忘了code
這樣咱們能夠用 容斥原理來遞推的計算GCD爲n*x的序列個數是多少blog
怎麼計算呢ci
以樣例爲例子 3 9string
當GCD = 3 的時候 能夠有9 / 3 = 3 個3 序列是這樣的 3 3 3it
那麼有三個空 用插板法 能夠計算能夠插板的方式數位2**(3-1) = 2**2 = 4種io
這裏解釋插板的意義 3|3 3插一個板就表示相鄰的數求和 那麼3|3 3 就是 6 3
同理 3 3|3 -> 3 6; 3|3|3 -> 9; 可是這樣插板出現了問題 就是出現了GCD 並不爲3的序列 即 9
這個時候就須要用容斥原理來 遞推
設a[i] 表示GCD爲i的序列個數, a[j] 表示GCD爲j個數
不妨設i > j
if (i % j == 0) a[j] = (a[j]+MOD-a[i]) % MOD; 由於 GCD 爲i的狀況是必定能夠經過插板 獲得GCD 爲j的狀況
而經過從大到小的遞推 a[i]已是容斥後的結果
這樣最終獲得GCD最小爲x 的結果就是答案 網上題解寫的有點不太清楚 這裏本身補充點本身的理解。輕噴。。
代碼君:
1 #include <bits/stdc++.h> 2 #include <string.h> 3 #include <iostream> 4 #include <stdio.h> 5 #define pb push_back 6 7 const int MOD = 1e9+7; 8 const int MAXN = 1e5+7; 9 typedef long long ll; 10 11 using namespace std; 12 13 ll x, y; 14 15 ll mypow(ll base, ll p) 16 { 17 if (p == 0) return 1; 18 ll tmp = mypow(base, p/2); 19 if (p & 1) tmp = (tmp*tmp*base) % MOD; 20 else tmp = (tmp*tmp) % MOD; 21 return tmp; 22 } 23 vector<ll> a; 24 ll dp[MAXN]; 25 int main() 26 { 27 //freopen("in.txt", "r", stdin); 28 while (cin >> x >> y) 29 { 30 a.clear(); 31 if (y % x != 0) 32 { 33 cout << 0 << endl; 34 continue; 35 } 36 for (ll i = 1; i*i <= y; i++) 37 { 38 if (i % x == 0 && y % i == 0) a.pb(i); 39 if (i*i != y && y % i == 0 && (y/i)%x==0 ) a.pb(y/i); 40 } 41 sort(a.begin(), a.end()); 42 for (int i = 0; i < a.size(); i++) dp[i] = mypow(2, (y/a[i]-1)); 43 for (int i = (int)a.size()-1; i >= 0; i--) 44 for (int j = i+1; j < a.size(); j++) 45 if (a[j] % a[i] == 0) 46 { 47 dp[i] -= dp[j]; 48 dp[i] = (dp[i] + MOD) % MOD; 49 } 50 cout << dp[0] << endl; 51 } 52 return 0; 53 }