其他分享
首页 > 其他分享> > Codeforces Round #450 (Div. 2) D. Unusual Sequences - 隔板法+容斥

Codeforces Round #450 (Div. 2) D. Unusual Sequences - 隔板法+容斥

作者:互联网

题目链接: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;
}
H_ang 发布了387 篇原创文章 · 获赞 22 · 访问量 2万+ 私信 关注

标签:Unusual,450,LL,容斥,len,int,tot,ans,mod
来源: https://blog.csdn.net/qq_21433411/article/details/104143637