题目链接:https://codeforces.com/contest/900/problem/D
题目大意:
给你一个x和y。求:
gcd(a1, a2, …, an) = x
的序列个数。
思路:如果y/x==0才可能满足条件。我们把每一堆大小定义成len=y/x那么就是有len个物品分配到m个盒子。盒子不能为空。
m=1…len。 那么可能的结果就是2^(len-1)。
但是这样的gcd可能不是x。例如:3 12分成6 6。
gcd=6。你们我们考虑可能出现的gcd是哪些。如果GCD=Z。
那么Z是x的倍数,并且Z是y的因数。因为x是y的因数。那么Z一定是y/x的因数。那么我们筛出y/x的素因子进行容斥就可以了。
#include<bits/stdc++.h>
#define LL long long
using namespace std;
int mod=1e9+7;
LL quick_pow(LL a, LL b)
{
LL ans=1;
while(b)
{
if(b&1)
ans=ans*a%mod;//ans*a%mod;
a=a*a%mod;//a=a*a%mod;
b>>=1;
}
return ans;
}
vector<int> v;
LL ans=0;
void dfs(int tot, int s, int len, int f){
if(tot==v.size()){
ans+=quick_pow(2, len/s-1)*f;
ans=(ans+mod)%mod;
return ;
}
dfs(tot+1, s*v[tot], len, -f);
dfs(tot+1, s, len, f);
}
int main(){
int x, y;
scanf("%d%d", &x, &y);
if(y%x==0){
int len=y/x;
for(int i=2 ;i*i<=len; i++){
if(len%i==0){
v.push_back(i);
while(len%i==0){
len/=i;
}
}
}
if(len!=1){
v.push_back(len);
}
//容斥
dfs(0, 1, y/x, 1);
printf("%lld\n", ans);
}
else{
printf("0\n");
}
return 0;
}