一個序列a1,…,an是合法的,當且僅當:
長度爲給定的n。
a1,…,an都是[1,A]中的整數。
a1,…,an互不相等。
一個序列的值定義爲它裏面所有數的乘積,即a1a2…an。
求所有不同合法序列的值的和。
兩個序列不同當且僅當他們任意一位不一樣。
輸出答案對一個數mod取餘的結果。
Input
一行3個數,A,n,mod。意義爲上面所說的。
Output
一行結果。
Sample Input
9 7 10007
Sample Output
3611
Hint
數據規模和約定
0:A<=10,n<=10。
1…3:A<=1000,n<=20.
4…9:A<=10^9,n<=20
10…19:A<=10^9,n<=500。
全部:mod<=10^9,並且mod爲素數,mod>A>n+1
思路:
考慮dp
dp[i]爲長度爲i時的結果
dp[i]怎麼表示呢,考慮這i個裏面可能有多少個相等的值
相等的值的個數可能是j=(1,2,3,4,…i),進行容斥即可
這j個相等的數的值可能是p=(1,2,3,4,…a),應該是p的j次冪的和,用拉格朗日插值求次冪之和
代碼:
typedef long long ll;
using namespace std;
const int MAXN=550;
const int inf=0x3f3f3f3f;
//const int mod=1e9+7;
//::iterator it;
inline int read(){
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;
}
ll n,A,mod;
ll quick(ll a,ll b){
ll ans=1;
while(b){
if(b&1)ans=(ans*a)%mod;
a=(a*a)%mod;
b/=2;
}
return ans;
}
ll inv(ll x){
return quick(x,mod-2);
}
ll f[MAXN];
ll fac[MAXN];
ll iiik(ll n,ll k){
for(ll i=1;i<=k+2;i++){
f[i]=(f[i-1]+quick(i,k))%mod;
}
if(n<=k+2){
return f[n];
}
ll p=1;
for(ll i=1;i<=k+2;i++){
p=(p*(n-i))%mod;
}
ll ans=0;
for(ll i=1;i<=k+2;i++){
ll m=1;
// ll v1=inv(n-i)%mod;
// ll v2=inv(fac[i-1]%mod*fac[k+2-i]%mod)%mod;
if((k+2-i)%2==1)m=-1;
m=((m*p%mod*f[i]%mod)*inv((n-i)*fac[i-1]%mod*fac[k+2-i]%mod))%mod;
//ans=(ans+m*v1*v2%mod*f[i]%mod*p%mod)%mod;
ans=(ans+m)%mod;
}
return (ans+mod)%mod;
}
ll ccc(ll n,ll m){
if(n<m)return 0;
return (fac[n] * quick(fac[m], mod - 2) % mod * quick(fac[n - m], mod - 2) % mod)%mod;
}
ll s[MAXN];
ll dp[MAXN];
int main()
{
std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
cin>>A>>n>>mod;
fac[0]=1;
for(ll i=1;i<=505;i++)fac[i]=(fac[i-1]*i)%mod;
dp[0]=1;
for(ll i=1;i<=n;i++){
s[i]=iiik(A,i);
for(ll j=1;j<=i;j++){
ll m=1;
if((j-1)&1)m=-1;
dp[i]=((dp[i]+m*ccc(i-1,j-1)*fac[j-1]%mod*s[j]%mod*dp[i-j]%mod)%mod+mod)%mod;
}
}
cout<<(dp[n]+mod)%mod<<endl;
return 0;
}
//i 1---n (-1)^(j-1) *ccc(i-1,j-1)*(j-1)!*s[j]*dp[i-j]
/*
9 7 10007
*/