教科书般的亵渎题解
教科书般的亵渎题解
先吐槽一波,这名字起的,没玩过游戏的人怕是都以为是什么题啊
洛谷P4593 [TJOI2018]教科书般的亵渎
题目描述
小豆喜欢玩游戏,现在他在玩一个游戏遇到这样的场面,每个怪的血量为ai,且每个怪物血量均不相同,小豆手里有无限张“亵渎”。亵渎的效果是对所有的怪造成1点伤害,如果有怪死亡,则再次施放该法术。我们认为血量为0怪物死亡
小豆使用一张 “亵渎”会获得一定的分数,分数计算如下,在使用一张“亵渎”之后,每一个被亵渎造成伤害的怪会产生xk,其中造成伤害前怪的血量为x和需要杀死所有怪物所需的“亵渎”的张数k。
输入格式
第一行输入一个T(T≤10),表示有多少组测试数据
每组组测试数据第一行为n,m,表示有当前怪物最高的血量n,和m种没有出现的血量
接下来m行,每行11个数a,表示场上没有血量为ai的怪物
输出格式
一共T行,每行一个数,第i行表示第i组测试数据中小豆的最后可以获得的分数, 因为这个分数会很大需要模10^9+7
输入输出样例
输入 #1 复制
2
10 1
5
4 2
1
2
输出 #1 复制
415
135
说明/提示
对于%10的数据,有m=0
对于%20的数据,有m≤1
对%30%的数据,有m≤2
对于%40%的数据,有m≤3
对于%50%的数据,有m≤4
对于%60%的数据,有m≤5
对于%100%的数据,有m≤50
对于%100%的数据,有n≤1013
题意:
开始看了半天想了5、6个小时不知道怎么做,结果发现理解错了题意,一定不是我的错,一定是题目的锅
有一种群体技能,每次能造成群体伤害一点,并且若有怪死亡会自动重放(不计入分数)。
每一次放技能会有xk分数,其中x为怪血量总和,k为杀死所有怪的最少放技能次数。
有两点要注意:1.技能会重放。2.k为初始值,是不变量,并不是当前量,作者惨死当场
对,你没看错,因为作者太弱,不知怎么概括,所以······,几乎就抄的题目
思路:
每个存在的怪都会有血量xk的分数贡献。
又仔细看题,发现m的范围极小。
所以想到容斥,答案即为:
(k=m+1)
你问为什么它是个k+1次多项式?
我也不是很清楚,或许可以参考这里。
则直接暴力枚举即可。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=56; 4 const long long mod=1e9+7; 5 int tt,m; 6 long long n,g,ans,a[N],t[N],x[N],y[N]; 7 inline long long read(){ 8 long long T=0,F=1; char ch=getchar(); 9 while(ch<'0'||ch>'9'){if(ch=='-') F=-1; ch=getchar();} 10 while(ch>='0'&&ch<='9') T=(T<<3)+(T<<1)+(ch-48),ch=getchar(); 11 return F*T; 12 } 13 long long ksm(long long u,long long v){ 14 long long base=u,answer=1; 15 while(v){ 16 if(v&1) answer=answer*base%mod; 17 base=base*base%mod,v>>=1; 18 } 19 return (answer+mod)%mod; 20 } 21 long long mul(long long k){ 22 g=1; 23 long long o,answer=0; 24 if(k<=m+3) return y[k]; 25 for(int i=1;i<=m+3;++i) g=g*(k-i+mod)%mod; 26 for(int i=1;i<=m+3;++i){ 27 o=ksm(k-i,mod-2)*g%mod*y[i]%mod*t[i]%mod; 28 answer=(answer+o+mod)%mod; 29 } 30 return answer; 31 } 32 long long init(int x){ 33 long long answer=0; 34 for(int i=x+1;i<=m;++i) answer=(answer+ksm(a[i]-a[x],m+1)+mod)%mod; 35 return answer; 36 } 37 int main(){ 38 tt=read(); 39 while(tt--){ 40 memset(t,0,sizeof(t)); memset(x,0,sizeof(x)); memset(y,0,sizeof(y)); memset(a,0,sizeof(a)); 41 n=read(),m=read(),a[0]=0,ans=0; 42 for(int i=1;i<=m;++i) a[i]=read(); 43 sort(a+1,a+m+1); 44 for(int i=1;i<=m+3;++i) x[i]=i,y[i]=(y[i-1]+ksm(i,m+1))%mod; 45 for(int i=1;i<=m+3;++i){ 46 t[i]=1; 47 for(int j=1;j<=m+3;++j) if(i!=j) t[i]=t[i]*(i-j+mod)%mod; 48 t[i]=ksm(t[i],mod-2); 49 } 50 for(int i=0;i<=m;++i) ans=(ans+mul(n-a[i])+mod-init(i))%mod; 51 printf("%lld\n",ans); 52 } 53 return 0; 54 }