一个序列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
*/