p4593 [TJOI2018]教科书般的亵渎

分析

我们发现$Ans = \sum_i \sum_j (j-p_i)^{m+1}$

因此直接套用622f的方法即可

代码

#include<bits/stdc++.h>
using namespace std;
const int N = 100;
const int mod = 1e9+7;
int a[110],p[110],inv[110],sum[110],Ans;
inline int pw(int x,int tot){
    int res=1;
    while(tot){
      if(tot&1)res=1ll*res*x%mod;
      x=1ll*x*x%mod;
      tot>>=1;
    }
    return res;
}
inline int work(int n,int k){
    int ans=0,i,t=1;
    for(i=1;i<=k+2;i++)sum[i]=(sum[i-1]+pw(i,k))%mod;
    if(n<=k+2){return sum[n];}
    for(i=1;i<=k+2;i++)t=1ll*t*(n-i)%mod;
    for(i=1;i<=k+2;i++){
      int res=1ll*sum[i]*t%mod*pw(n-i,mod-2)%mod*inv[k+2-i]%mod*inv[i-1]%mod;
      if((k+2-i)&1)res=mod-res;
      ans=(ans+res)%mod;
    }
    return ans;
}
int main(){
    int n,m,i,j,t;
    scanf("%d",&t);
    p[0]=1;
    for(i=1;i<=N;i++)p[i]=1ll*p[i-1]*i%mod;
    inv[N]=pw(p[N],mod-2);
    for(i=N-1;i>=0;i--)inv[i]=1ll*inv[i+1]*(i+1)%mod;
    while(t--){
      scanf("%d%d",&n,&m);
      for(i=1;i<=m;i++)scanf("%d",&a[i]);
      sort(a+1,a+m+1);
      for(i=m;i>0;i--)
        if(a[i]==n)n--,m--;
          else break;
      Ans=0;
      for(i=0;i<=m;i++)
        Ans=(Ans+work(n-a[i],m+1))%mod;
      for(i=1;i<=m;i++)
        for(j=0;j<i;j++)
          Ans=(Ans-pw(a[i]-a[j],m+1)+mod)%mod;
      printf("%d\n",Ans);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/yzxverygood/p/11470823.html