题目链接: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;
}