zoukankan      html  css  js  c++  java
  • poj1091:跳蚤【容斥原理】

    题目大意:中文题就不翻译了

    思路:假设跳蚤选择X1个第一张卡片,X2个第二张卡片。。。Xn个第n张卡片,Xn+1张写着m的卡片,那么就可以列出方程:a1*X1+a2*X2+…+an*Xn+m*X(n+1)=1

    由于可以向左跳和向右跳,因此题目即问上述不定方程是否有解?答案以及它的证明可以在任何一本数论书中找到,它的充要条件是(a1,a2,a3。。。an,m)|1 即a1,a2,a3。。。an,m互质,这样题目就成为:有n+1个正整数,其中最大的数为m,问所有符合条件的序列中有多少是互质的。

    组合数学很多都是正难则反易的,考虑问题的背面有多少最大公约数不为1的?先把m分解质因数,m的每一个因子可以看成一个集合,集合中的元素为最大公约数为这个因子的序列,这个问题的答案便是所有集合的并中集合的元素,用容斥就显然了

    最后将总数m^n减去最大公约数不为1的个数,结果就是互质的个数了

    顺便吐槽下,虽然容斥属于集合论里面的东西,但经常用来证明数论题目,最早学它好像就是用来推导欧拉函数的公式时用的

    #include <cstdio>

    #include <string>

    #include <iostream>

    #include <math.h>

    #define ll __int64

    using namespace std;

    llfactor[100000],h=0,stack[100000],top=0,mt,nt,ret1;

    ll quickpow(ll n,ll m)

    {

       ll ret=1;

       while (m)

        {

           if ((m & 1))ret*=n;

           n*=n;

           m>>=1;

        }

       return ret;

    }

    void dfs(ll step,ll now,ll layer,ll num)

    {

       if (step==layer){ret1+=quickpow(mt/num,nt);return ;}

       for(inti=now+1;i<=h-layer+step+1;i++)dfs(step+1,now+1,layer,num*factor[i]);

    }

    int main()

    {

       ll n;

       scanf("%I64d%I64d",&nt,&mt);

       n=mt;

       while ((n & 1)==0){h=1;factor[h]=2;n>>=1;}

       ll q=sqrt(n);

       for(ll i=3;i<=q && n!=1;i+=2)

        {

           if (n % i==0)factor[++h]=i;

           while(n%i==0)n=n/i;

        }

       if (n!=1)factor[++h]=n;

       ll ans=0,flag=-1;

       for(ll i=1;i<=h;i++)

        {

           flag*=-1;

           top=ret1=0;

           dfs(0,0,i,1);

           ans+=ret1*flag;

        }

       printf("%I64d ",(ll)quickpow(mt,nt)-ans);

       return 0;

    }

  • 相关阅读:
    java Cache
    世界上第一个免费的云
    网上看到的一些IT资源
    图片压缩优化kraken
    Asp.net MVC Comet推送
    jQuery插件开发方式
    jQuery之Nestable
    jqGrid使用记录
    Windbg符号与源码 《第二篇》
    jQuery 获取 URL信息
  • 原文地址:https://www.cnblogs.com/philippica/p/4007004.html
Copyright © 2011-2022 走看看