poj 1091 跳蚤

来源:互联网 发布:js基本数据类型有几种 编辑:程序博客网 时间:2024/06/11 03:43

题目大意:给你两个数n与m,n代表跳蚤共可以走n+1步,规定最后一步的步长为m,前n步的步长可以为1,2,......,m之中的任意一个。对于每一步步长,跳蚤可以选择向左跳或向右跳相应的长度,如果经过n+1步后,跳蚤能向左移动一步,则称该套步长集符合条件。问总共有多少套符合要求的步长集。

思路:令跳的步长为a[1],a[2],......,a[n+1],将相同长度的步长合并后,问题则转化为对于一组数串b[1],b[2],.. ... ,b[k],是否存在x[1],x[2],... ...,x[k],满足b[1]*x[1]+b[2]*x[2]+... ... +b[k]*x[k]=1,若存在,则步长满足条件。根据扩展欧几里得定理可得,若gcd(b[1],b[2],... ... ,b[k]) = 1,则符合条件。然后按照容斥定理,依次删去不符合条件的步长集,剩下的就是符合条件的。

 

#include <iostream>#include <cstdio>#include <vector>using namespace std;__int64 n,m,ans,sum;vector<__int64> factor,mul_factor;__int64 int64_pow(__int64 buttom,__int64 index){    __int64 res=1,i;    for (i=1;i<=index;i++)        res*=buttom;    return res;}void mfind(__int64 start_pos,__int64 cnt,__int64 capacity){    __int64 mm=m,i;    if (cnt==capacity)    {        for (i=0;i<capacity;i++)            mm/=mul_factor[i];        sum+=int64_pow(mm,n);    }    else        for (i=start_pos;i<factor.size();i++)        {            mul_factor.push_back(factor[i]);            mfind(i+1,cnt+1,capacity);            mul_factor.pop_back();        }}int main(){    __int64 i,mm,sign;    while (scanf("%I64d%I64d",&n,&m)==2)    {        ans=int64_pow(m,n);        factor.clear();        mm=m;        for (i=2;i*i<=mm;i++)            if (mm%i==0)            {                while (mm%i==0)                    mm/=i;                factor.push_back(i);            }        if (mm!=1)            factor.push_back(mm);        for (i=1,sign=-1;i<=factor.size();i++)        {            sum=0;            mul_factor.clear();            mfind(0,0,i);            ans+=sum*sign;            sign*=-1;        }        printf("%I64d\n",ans);    }    return 0;}