codeforces 900D 数论+组合+容斥原理

问有多少个这样的数字序列

所有数的GCD等于x 并且 所有数的和等于y

题解:

非常难有思路啊 看题解后过的。

考虑序列GCD为x的倍数 即GCD = n*x 和当然都为y 这个条件不要忘了

这样我们可以用  容斥原理来递推的计算GCD为n*x的序列个数是多少

怎么计算呢

以样例为例子 3 9

当GCD = 3 的时候 可以有9 / 3 = 3 个3 序列是这样的 3 3 3

那么有三个空 用插板法 可以计算可以插板的方式数位2**(3-1) = 2**2 = 4种

这里解释插板的意义 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 }    
View Code

 

posted @ 2018-03-06 20:13  Lorazepam  阅读(200)  评论(0编辑  收藏  举报