1. 程式人生 > >洛谷1771 方程的解

洛谷1771 方程的解

題目描述

佳佳碰到了一個難題,請你來幫忙解決。

對於不定方程a1+a2+…+ak-1+ak=g(x),其中k≥2且k∈N,x是正整數,g(x)=x^x mod
1000(即x^x除以1000的餘數),x,k是給定的數。我們要求的是這個不定方程的正整數解組數。

舉例來說,當k=3,x=2時,分別為(a1,a2,a3)=(2,1,1)’(1,2,1),(1,1,2)。 輸入輸出格式 輸入格式:

輸入檔案equation.in有且只有一行,為用空格隔開的兩個正整數,依次為k,x。

輸出格式:

輸出檔案equation.out有且只有一行,為方程的正整數解組數。

快速冪求出g(x)。
考慮裸的dp方程,dp[i][j]表示i個數和為j的方案數,dp[i][j]=Σdp[i-1][i-1…j-1],時間複雜度為O(k*mod^2)。
注意到邊界條件dp[0][0]=1,其他所有值都由它推得,從刷表的角度考慮,dp[i][j]每次一定走到dp[i+1][j+x],最終要走到dp[k][g]。不妨看成要走k步,每一步可以走一個或一個以上的格子,最後總共要走g個格子,問方法總數。
這樣就變成了計數問題,即要在(g-1)個間隔中選出(k-1)個,答案是c(g-1,k-1)。
注意使用高精度。

#include<cstdio>
#include<cstring>
#include<algorithm> using namespace std; #define LL long long const int bit=10000; const int mod=1000; struct NUM { int a[100],l; NUM operator + (const NUM & x) { NUM ret; ret.a[1]=0; for (int i=1;i<=l||i<=x.l;i++) { ret.a[i]+=a[i]+x.a[i]; ret.a[i+1
]=ret.a[i]/bit; ret.a[i]%=bit; } ret.l=max(l,x.l); if (ret.a[ret.l+1]) ret.l++; return ret; } void out() { int i,j,k,x,y,z; printf("%d",a[l]); for (i=l-1;i;i--) { if (a[i]<10) printf("000"); else { if (a[i]<100) printf("00"); else { if (a[i]<1000) printf("0"); } } printf("%d",a[i]); } printf("\n"); } }c[1010][110]; int pw(int x) { int base=x%mod,ans=1; for (;x;x>>=1,base=(base*base)%mod) if (x&1) ans=(ans*base)%mod; return ans; } int main() { int i,j,k,m,n,p,q,x,y,z; scanf("%d%d",&k,&x); m=pw(x); for (i=0;i<m;i++) c[i][0].a[1]=c[i][0].l=1; for (i=1;i<m;i++) for (j=1;j<k;j++) c[i][j]=c[i-1][j-1]+c[i-1][j]; c[m-1][k-1].out(); }