【数论】君と彼女の恋

来源:互联网 发布:js中的字符串截取 编辑:程序博客网 时间:2024/05/01 15:20
神 「肯定 。美雪 准备了两个 变数 ,记它们为 n和m」

神 「找到一个非 空的非负整数序列 S,满足 S的所有元素之和为 n,而且每个元素对 m取模得到的结果都不相同 」

神 「这种 序列的个数 ,对神的电话号码取模, 就是 命运的数字 」

更加 听不明白 了…… 但是 你能懂的吧。

【嗯…… 怎样 的两个序列算是不同的?】

神 「只要长度不相同,或者 存在 一位 不同 的元素,即为不同序列 」

对于 100% 的数据, n≤10^18,m≤100。

鸽笼原理,数列长度最多为100,考虑状压DP,用fij表示余数选出i个时和为j的方案数,我们可以枚举每个余数,假如选出了cnt个余数,如果n-所有余数之和tot能被m整除,那么这个余数集合合法,接下来给每个数加上m的非负整数倍,并求这样的集合的方案数,等于把(n-tot)/m个无标记小球放入cnt个箱子中,用隔板法求方案数为C(n-tot+cnt-1)(cnt-1),所以这个合法的余数集合的方案数为cnt的阶乘乘上前面那个方案数,然而这还是会T,所以我们不考虑选出哪一个余数,因为只有序列长度和对应的余数和才会影响答案,所以我们用fij来表示集合长度为i,余数和为j的方案数,用类似背包的转移就可以A了,总复杂度O(m^4)

#include<cctype>#include<cstdio>#include<map>#include<cmath>#include<queue>#include<vector>#include<cstring>#include<cstdlib>#include<iostream>#include<iomanip>#include<algorithm>#define mod 905229641#define LL long longusing namespace std;LL read(){    LL x=0,f=1;char ch=getchar();    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}    return x*f;}LL f[100][5100],n,m;LL q,an;void bei(){        memset(f,0,sizeof(f));        f[0][0]=1;        for (int k=0;k<m;k++)                for (int i=k;i>=0;i--)                        for (int j=k*(k-1)/2;j>=0;j--)        {                f[i+1][j+k]=(f[i+1][j+k]+f[i][j])%mod;        }}/*void gcd(LL a,LL b){        if (b==0)        {                x=1;                y=0;                return;        }        gcd(b,a%b);        LL t=x;        x=y%mod;        y=(t-a/b*y%mod)%mod;}LL multi(LL a,LL b,LL c){        int ans=1;        a=a%c;        while(b>0)        {                if(b%2==1)                ans=(ans*a)%c;                b=b/2;                a=(a*a)%c;        }        return ans;}*/int main(){        n=read();m=read();        int sum=m*(m-1)/2;        bei();        LL ans=0;        for (int i=0;i<=sum;i++)                if ((n-i)%m==0)        {                for (int j=1;j<=m;j++)                        {                                LL xx=(n-i)/m;                                an=(xx+j-1)%mod;                                int sum=1;                                 for (int k=1;k<j;k++)                                {                                        sum=sum*an % mod;                                        an--;                                }                                sum=sum*(j*f[j][i]%mod)%mod;                                ans=(ans+sum)%mod;                        }//                                cout<<an<<' '<<q<<' '<<f[k][i]<<' '<<k<<' '<<i<<endl;        }        cout<<ans<<endl;        return 0;}


0 0
原创粉丝点击