下面是BC官方题解:这题的本质是求 x1+x2+x3+……+xm=n 且 x1>x2,x3,x4,……,xm 这个方程有多少整数解。 可以枚举 x1.设当前 x1=u,那么问题转化为求 x1+x2+x3+……+xm=n−u 且 u>x2,x3,x4,……,xm,可以用生成函数来解决。 每一个项的生成函数是 f(x)=1+x+x2+……+xu−1=1−xu1−x 那么m−1个相加的生成函数是 G(x)=[f(x)]m−1=(1−xu)m−1(1−x)m−1 再利用(1+x)k=1+∑n=1∞k∗(k−1)∗(k−2)∗……∗(k−n+1)n!xn对上边的分子分母进行展开。枚举分子中xu的次数,求出G(x)里xn−u的系数。总的复杂度是nlogn
不过题解讲的不是很清楚,对于1/(1-x)可以生成1+x+x^2+x^3...然后1/(1-x)^m也可以同样拆,对于分母就是一个多项式,直接枚举分母的次幂就行。
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> using namespace std; const int mod=1000000007; const int maxn=100005; typedef long long LL; LL jie[maxn<<1],fan[maxn<<1]; LL mm(int n,int m){ LL s=1; LL k=n; while(m>0){ if(m&1){ s=s*k; s%=mod; } k=k*k; k%=mod; m>>=1; } return s; } void init(void){ int i; jie[0]=1; fan[0]=1; for(i=1;i<=200000;i++){ jie[i]=jie[i-1]*i; jie[i]%=mod; fan[i]=mm(jie[i],mod-2); } } LL zuhe(int n,int m){ LL s; s=jie[n]*fan[m]; s%=mod; s=s*fan[n-m]; s%=mod; return s; } void solve(int n,int m){ int i,j; LL s=1; if(m==1){ cout<<"1"<<endl; return ; } int p; for(i=1;i<n;i++){ p=1; for(j=0;j*i<=n-i&&j<=m-1;j++){ LL s1=0; if(j<=m-1){ s1=zuhe(m-1,j)*zuhe(n-i-(j*i)+m-2,m-2)*p; s1%=mod; } s+=s1; s%=mod; p=p*-1; } } cout<<s<<endl; } int main() { init(); int n,m,t; cin>>t; while(t--){ cin>>n>>m; solve(n,m); } }
本文介绍了一种使用生成函数解决特定整数解计数问题的方法。通过枚举最大变量值并利用组合数学技巧,文章详细阐述了如何计算形如x1+x2+...+xm=n且x1>x2,...,xm的方程整数解数量,重点在于生成函数的构造与系数提取。

2855

被折叠的 条评论
为什么被折叠?



