zoukankan      html  css  js  c++  java
  • CF(439E

    题意:将n个糖果插入f-1个挡板分成f分(a1,a2,a3...af)。

    问有多少种分法能够使得gcd(a1,a2,a3...af)=1;


    解法。莫比乌斯容斥,首先按1为单位分,这时候有C(n-1,f-1)种,然后去掉gcd不是1的。这时候就规定质因子个数是奇数的就减(mou值为-1),偶数的为加(mou值是+1),然后出现平方数为约数的数mou值为0。这样就做到了容斥,非常巧妙。

    容斥时,要注意仅仅用计算是n的约数的数,由于假设不是n的约数,那么gcd里一定不会出现这个因子。


    代码:

    /******************************************************
    * author:xiefubao
    *******************************************************/
    #pragma comment(linker, "/STACK:102400000,102400000")
    #include <iostream>
    #include <cstring>
    #include <cstdlib>
    #include <cstdio>
    #include <queue>
    #include <vector>
    #include <algorithm>
    #include <cmath>
    #include <map>
    #include <set>
    #include <stack>
    #include <string.h>
    //freopen ("in.txt" , "r" , stdin);
    using namespace std;
    
    #define eps 1e-8
    #define zero(_) (abs(_)<=eps)
    const double pi=acos(-1.0);
    typedef long long LL;
    const int Max=100010;
    const int INF=1000000007;
    
    int mou[Max];
    LL fac[Max];
    map<pair<int,int>,LL> maps;
    int n,f;
    LL pow(LL a,int b)
    {
        LL ans=1;
        while(b)
        {
            if(b&1)
                ans=(ans*a)%INF;
            a=(a*a)%INF;
            b>>=1;
        }
        return ans;
    }
    LL getreverse(LL lo)
    {
        return pow(lo,INF-2);
    }
    void init()
    {
        for(LL i=2; i<Max; i++)
            if(!mou[i])
            {
                mou[i]=i;
                for(LL j=i*i; j<Max; j+=i)
                    mou[j]=i;
                   // cout<<i<<" ";
            }
        mou[1]=1;
        for(int i=2; i<Max; i++)
        {
            if((i/mou[i])%mou[i]==0) mou[i]=0;
            else mou[i]=-mou[i/mou[i]];
        }
        fac[0]=1;
        for(int i=1; i<Max; i++)
            fac[i]=(fac[i-1]*i)%INF;
    }
    LL C(int a,int b)
    {
        LL ans=fac[a];
        ans=(ans*getreverse(fac[a-b])%INF*getreverse(fac[b]))%INF;
        return ans;
    }
    int main()
    {
        int t;
        cin>>t;
        init();
        while(t--)
        {
            scanf("%d%d",&n,&f);
            if(maps.find(pair<int,int>(n,f))!=maps.end())
            {
                printf("%I64d
    ",maps[pair<int,int>(n,f)]);
                continue;
            }
            LL ans=0;
            for(int i=1; i<=n/f; i++)
            {
                if((n%i)!=0)continue;
                ans+=C(n/i-1,f-1)*mou[i];
                if(ans>=INF)
                    ans-=INF;
                if(ans<0)
                    ans+=INF;
            }
            printf("%I64d
    ",ans);
            maps[pair<int,int>(n,f)]=ans;
        }
        return 0;
    }
    

查看全文
  • 相关阅读:
    Open source cryptocurrency exchange
    Salted Password Hashing
    95. Unique Binary Search Trees II
    714. Best Time to Buy and Sell Stock with Transaction Fee
    680. Valid Palindrome II
    Java compiler level does not match the version of the installed Java project facet.
    eclipse自动编译
    Exception in thread "main" java.lang.StackOverflowError(栈溢出)
    博客背景美化——动态雪花飘落
    java九九乘法表
  • 原文地址:https://www.cnblogs.com/ldxsuanfa/p/10589070.html
  • Copyright © 2011-2022 走看看