(UVA

来源:互联网 发布:全国流动人口监测数据 编辑:程序博客网 时间:2024/06/05 08:47

链接: https://vjudge.net/problem/UVA-10943

题意:把K个不超过N的非负整数加起来,使它们的和为N,有多少种方法?
例如:N=5,K=2有6种,0+5,1+4,2+3,3+2,4+1,5+2
输入N和K,(1<=N,K<=100),输出方法总数除以10^6的余数

分析:题意可以转化为 x1+x2+x3+……+xk=N的非负数解的种类数
由组合数可以得到答案是C(n+k-1,n)
相当于隔板

复杂度O(n^2)

#include <cstdio>#include <cstring>#include <iostream>#include <cmath>#include <algorithm>#include <sstream>#include <string>#include <set>#include <map>using namespace std;#define mem(a,n) memset(a,n,sizeof(a))typedef long long LL;const int mod=1e6;const double eps=1e-6;const int INF=0x3f3f3f3f;const int N=205;int C[N][N];void init(){    mem(C,0);    for(int i=0; i<=N; i++)        C[i][0]=C[i][i]=1;    for(int i=1; i<=N; i++)        for(int j=1; j<i; j++)            C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;}int main(){    init();    ios::sync_with_stdio(false);    int n,k;    while(cin>>n>>k)    {        if(!n&&!k) break;        int ans=C[n+k-1][n];        cout<<ans<<endl;    }    return 0;}

可以进一步优化,复杂度为O(n)
其中用到了C(n,k+1)=C(n,k)*(n-k)/(k+1), 处理时注意溢出的情况。
写了一下,但是WA了,应该不会溢出吧?

WA的代码:

#include <cstdio>#include <cstring>#include <iostream>#include <cmath>#include <algorithm>#include <sstream>#include <string>#include <set>#include <map>using namespace std;#define mem(a,n) memset(a,n,sizeof(a))typedef long long LL;const int mod=1e6;const double eps=1e-6;const int INF=0x3f3f3f3f;const int N=205;LL C[N][N];LL n,k;LL pow_mod(LL a,LL b){    LL ans=1;    a%=mod;    while(b)    {        if(b&1) ans=ans*a%mod;        b>>=1;        a=a*a%mod;    }    return ans;}LL fermat(LL a,LL p){    return pow_mod(a,p-2);}void init(int n){    C[n+k-1][0]=1;    for(LL i=1; i<n; i++)    {        C[n+k-1][i]=(1LL*C[n+k-1][i-1]*(n+k-1-i+1)*pow_mod(i,mod))%mod;    }}int main(){    ios::sync_with_stdio(false);    while(cin>>n>>k)    {        if(!n&&!k) break;        init(n);        int ans=C[n+k-1][k-1];        cout<<ans<<endl;    }    return 0;}
原创粉丝点击