方程的解

题目链接:

Description

佳佳碰到了一个难题,请你来帮忙解决。

对于不定方程 \(a1+a2+⋯+ak−1+ak=g(x)\),其中 \(k≥1\)\(k∈N∗\)\(x\) 是正整数,\(g(x)=x^xmod1000\)(即 x 除以 1000 的余数),\(x,k\) 是给定的数。

我们要求的是这个不定方程的正整数解组数。

举例来说,当 \(k=3,x=2\) 时,方程的解分别为:
\(1:a_1=1,a_2=1,a_3=2;\)
\(2:a_1=1,a_2=2,a_3=1;\)
\(3:a_1=2,a_2=1,a_3=1;\)

Input

有且只有一行,为用空格隔开的两个正整数,依次为 \(k,x\)
\(1≤k≤100,\)
\(1≤x<231,\)
\(k≤g(x)\)

Output

有且只有一行,为方程的正整数解组数。

Sample Input

3 2

Sample Output

3

题意

求k个大于0的数凑成\(x^x%1000\)的方案数之和

题解:

隔板法求解等式:\(a1+a2+⋯+ak−1+ak=n\)。可以用快速幂求出\(n=x^x%1000\)。我们把n想象成n个水平排列的小球,我们需要把这些小球用挡板分成k部分,每一部分都大于0。
\(eg:n=8,k=4\),我们可以在n-1个空隙中选择k-1插入挡板,第i个挡板的前面的小球数对应\(a_i\),第k-1个挡板后面的球数等于\(a_k\)

代码

#include<bits/stdc++.h>
using namespace std;
int qmi(int a,int b){ 
    int res=1;
    while(b){
        if(b&1) res=1ll*res*a%1000;
        b>>=1;
        a=1ll*a*a%1000;
    }
    return res;
}
int f[1010][101][200];
void add(int a[],int b[],int c[]){
    for(int i=0;i<199;++i){
        a[i]+=b[i]+c[i];
        a[i+1]+=(a[i])/10;
        a[i]%=10;
    }
}
int main(){
    int k,x;
    cin>>k>>x;
    x=qmi(x,x);
    if(x==0){
        cout<<0<<endl;
        return 0;
    }
    for(int i=0;i<=x;++i){
        for(int j=0;j<k&&j<=i;++j)
            if(!j)f[i][j][0]=1;
            else add(f[i][j],f[i-1][j-1],f[i-1][j]);
    }
    int i=199;
    while(f[x-1][k-1][i]==0&&i!=0) --i;
    while(i>=0) cout<<f[x-1][k-1][i--];
    return 0;
}
posted @ 2020-04-16 22:40  0x4f  阅读(223)  评论(0编辑  收藏  举报