GCD of Sequence
Alice is playing a game with Bob.
Alice shows N integers a 1, a 2, …, a N, and M, K. She says each integers 1 ≤ a i ≤ M.
And now Alice wants to ask for each d = 1 to M, how many different sequences b 1, b 2, …, b N. which satisfies :
1. For each i = 1…N, 1 ≤ b[i] ≤ M
2. gcd(b 1, b 2, …, b N) = d
3. There will be exactly K position i that ai != bi (1 ≤ i ≤ n)
Alice thinks that the answer will be too large. In order not to annoy Bob, she only wants to know the answer modulo 1000000007.Bob can not solve the problem. Now he asks you for HELP!
Notes: gcd(x 1, x 2, …, x n) is the greatest common divisor of x 1, x 2, …, x n
Input
The input contains several test cases, terminated by EOF.
The first line of each test contains three integers N, M, K. (1 ≤ N, M ≤ 300000, 1 ≤ K ≤ N)
The second line contains N integers: a 1, a 2, …, a n (1 ≤ a i ≤ M) which is original sequence.
Output
For each test contains 1 lines :
The line contains M integer, the i-th integer is the answer shows above when d is the i-th number.
Sample Input
3 3 3
3 3 3
3 5 3
1 2 3
Sample Output
7 1 0
59 3 0 1 1
Hint
In the first test case :
when d = 1, {b} can be :
(1, 1, 1)
(1, 1, 2)
(1, 2, 1)
(1, 2, 2)
(2, 1, 1)
(2, 1, 2)
(2, 2, 1)
when d = 2, {b} can be :
(2, 2, 2)
And because {b} must have exactly K number(s) different from {a}, so {b} can't be (3, 3, 3), so Answer = 0
题意:
给你一个数数组a[i],其中给出的每一个数字和要求的数字都是属于[1,m],现在问你根据a[]a[i],其中给出的每一个数字和要求的数字都是属于[1,m],现在问你根据a[]构造一个b[],且a和b中间的不相等的元素的个数恰好有kb[],且a和b中间的不相等的元素的个数恰好有k个。
现在问你gcd(b[])分别为1,2,……,m的个数分别有多少种可能情况gcd(b[])分别为1,2,……,m的个数分别有多少种可能情况。
分析:
通过以往的做题经验我们知道,对于求一个范围内含有确定的因数dd的个数并不好求,但是好求的是一个范围内含有因数
那么对于这道题我们思路可以从大到小枚举m假设枚举的数是i,我们首先可以求出mi,我们首先可以求出m范围内有多少个数因子含有i及其i的倍数及为num=mi(mi及其i的倍数及为num=mi(m范围内只有这么多,这是全部)
那么实际给定的aa数列中有多少是满足这个条件的数呢?
我们输入时完全可以记录每个数的个数(因为为步长统计出a数列中的含有i及其i的倍数作为因子的数的个数及为cura数列中的含有i及其i的倍数作为因子的数的个数及为cur
那么总数n减去这个个数剩下的就是an减去这个个数剩下的就是a数列中不满足条件的数的个数即n−curn−cur
这个时候我们就需要判断,因为我们只能确定的修改k个值,那么这时就分了三种情况
1)n−cur>k:n−cur>k:
说明剩下的需要修改的数大于k个才能保证每个数含有因子是为i及其i的倍数从而保证gcd=ik个才能保证每个数含有因子是为i及其i的倍数从而保证gcd=i,而题目要求我们只能该k个那么在这种情况下将没有符合条件的bb数列,因而答案为0。
2)
此时说明剩下的数恰好k个那么我们直接修改即可了根据上面我们知道共有num=minum=mi种选择,共有k个需要选因此共有numn−cur=numknumn−cur=numk种
3)n−cur<k:n−cur<k:
说明剩下的a数列中不满足条件的数的个数小于k个,而我们又必须要该ka数列中不满足条件的数的个数小于k个,而我们又必须要该k个,因此我们只能再从已将满足条件的数中再修改cur+k−ncur+k−n个,因此这cur+k−ncur+k−n需要从满足条件的curcur中选,此时便需要用到组合数Ccur+k−ncurCcurcur+k−n中,而每个我们可以替换的数是num中除去anum中除去a中原来那个数本身,因此每个位置还有num−1num−1种选择即(num−1)cur+k−n(num−1)cur+k−n,所以这种情况下我们除了需要把n−curn−cur个不满足条件的位置修改,该需要把cur+k−ncur+k−n个已经满足条件的修改以凑够修改k个数
因此答案为情况2和情况3的组合即为
综上我们就求得了b数组的gcd为i即ib数组的gcd为i即i的倍数的所有可能情况
我们当然不想要gcd为i的倍数的情况,因此需要减去,这时就体现出了mgcd为i的倍数的情况,因此需要减去,这时就体现出了m从大到小枚举的好处,我们发现当我们求得i是i得i是i的倍数的情况已经求出来了,因此我们只需要在遍历一遍i的倍数的答案之间减去即可。
code:
#include <bits/stdc++.h>
using namespace std;
const int maxn = 300003;
const int mod = 1e9+7;
typedef long long ll;
int a[maxn],f[maxn],n,m,k,ai,tep;
ll P[maxn],Q[maxn];
ll q_pow(ll a,ll b){
ll ans = 1;
while(b){
if(b & 1)
ans = ans * a % mod;
a = a * a % mod;
b >>= 1;
}
return ans;
}
ll C(ll x,ll y){
if(y == 0 || x == y) return 1;
ll ans = P[x] * Q[y] % mod;
ans = ans * Q[x-y] % mod;
return ans;
}
int main(){
ll cur,tot,num;
Q[1] = P[0] = 1;
for(int i = 1; i < maxn; i++){
P[i] = (P[i-1] * i) % mod;
Q[i] = q_pow(P[i],mod-2);
}
while(scanf("%d%d%d",&n,&m,&k) != EOF){
for(int i = 1; i <= m; i++) a[i] = f[i] = 0;
for(int i = 1; i <= n; i++){
scanf("%d",&ai);
a[ai]++;
}
for(int i = m; i > 0; i--){
cur = 0;
tot = 1;
num = m / i;
for(int j = i; j <= m; j += i) cur += a[j];
if(n - cur > k){
f[i] = 0;
continue;
}
tot = q_pow(num,n-cur);
if(n - cur != k){
tep = C(cur,k+cur-n) * q_pow(num-1,k+cur-n) % mod;
tot = tot * tep % mod;
}
f[i] = tot;
for(int j = i + i; j <= m; j += i){
f[i] -= f[j];
if(f[i] < 0) f[i] += mod;
}
}
printf("%d",f[1]);
for(int i = 2; i <= m; i++){
printf(" %d",f[i]);
}
printf("\n");
}
return 0;
}
实际上经过上面的分析我们发现,上面我们说的三种情况实际上都可以用第三种情况表示即
这个公式可以完整的表示三种情况
而且这是求的gcd = i的倍数的个数
由此我们想到了莫比乌斯反演
此时的
所以
只要预处理数F(d)数F(d),然后直接求和累加即可,代码就不再写了,只说一下莫比乌斯反演的思路