「PKUWC2018」Slay the Spire
國(guó)際慣例不放題干
扯淡
其實(shí)題目翻譯過(guò)來(lái)是殺戮尖塔,某steam上的卡牌游戲,我也曾熱衷刷榜
題解
首先題目中要求的期望是假期望,結(jié)合題目中所給的階乘就可以看出這其實(shí)是從$2*n$張牌中選擇$m$張牌使用,并且所有情況都取最大值時(shí)的和
首先排序貪心最大
再說(shuō)一個(gè)非常顯然的結(jié)論,有強(qiáng)化牌就用,強(qiáng)化牌上數(shù)大于2,所以打出強(qiáng)化牌一定收益>=比打出一張攻擊牌帶來(lái)(保證最后一定要出至少一張攻擊牌就行)
例如? 你有強(qiáng)化牌? 2 2 攻擊牌 4 4 限制出2張
那么你先打一張2再打一張4和 先打4 再打4 收益一樣 ?
那么如果強(qiáng)化牌比k張要小,那么要把所有強(qiáng)化牌都用了,最后打輸出.如果強(qiáng)化牌比k還要大,那么最后留一張攻擊牌打出來(lái)就行了
我們可以假設(shè)$F(i,j)$表示你有i張強(qiáng)化牌時(shí)打出j張時(shí)收益,$G(i,j)$表示你有i張攻擊牌時(shí)打出j張時(shí)收益
那么最后答案就是
$\sum\limits_{i=0}^{k-1} F(i,i)*G(m-i,k-i)+\sum\limits_{i=k}^{k=min(n,m)} F(i,k-1)*G(m-i,1)$
那么我們現(xiàn)在的任務(wù)就是快速求出來(lái)F和G
考慮直接求非常難求,我們這時(shí)一般要開(kāi)幾個(gè)別的數(shù)組
首先開(kāi)$f[i][j]$ $g[i][j]$表示當(dāng)你抽到i張牌必打第i張一共打了j張時(shí)收益
那么可以推出來(lái)$f[i][j]=w_i\times \sum f[l][j-1]$和$g[i][j]=C_{i-1}^{j-1}w_i + \sum g[l][j-1]$ (這里的組合數(shù)表示一共有$C_{i-1}^{j-1}$種方式轉(zhuǎn)移過(guò)來(lái),每種轉(zhuǎn)移都要加一個(gè)w)
然后得到$F(i,j)=\sum_{l=j}^{n} C_{n-l}^{i-j} f[l][j]$
解釋一下 F可以從l中使用j張(這j張都是大牌)再?gòu)氖S鄋-l中選擇i-j張不打共同構(gòu)成F的i張打了j張
G同理得到$G(i,j)=\sum{l=j}^{n} C_{n-l}^{i-j} g[i][j]$
然后轉(zhuǎn)移就完了
本題稍卡常
代碼
#include<bits/stdc++.h> using namespace std; #define ll long long #define A 1510 #define py printf("f**k\n") #define mod 998244353 ll n,m,t,k,ans=0,f[1510][1510],g[1510][1510],C[3010][3010],sum1[A],sum2[A],wg[A],wq[A]; inline ll read() {ll x=0; char c=getchar();while(isdigit(c)){x=x*10+c-'0';c=getchar();}return x; } ll gcd(ll x,ll y){if(y==0) return x;return gcd(y,x%y); } inline ll F(ll i,ll j){ll r=0;for(ll l=j;l<=n;l++){r=(r+C[n-l][i-j]*f[l][j]%mod)%mod;//表示含義為首先從前l(fā)張選出j張?jiān)購(gòu)膎-l中選出l-j張 }return r; } inline bool cmp(const ll & a,const ll & b){return a>b; } inline ll G(ll i,ll j){ll r=0;for(ll l=j;l<=n;l++){r=(r+C[n-l][i-j]*g[l][j]%mod)%mod;//含義同上 }return r; } inline void re(){memset(sum1,0,sizeof(sum1));memset(sum2,0,sizeof(sum2)); } inline void init(){n=read(),m=read(),k=read();f[0][0]=1;for(ll i=1;i<=n;i++)wq[i]=read();sort(wq+1,wq+n+1,cmp);for(ll i=1;i<=n;i++)wg[i]=read();sort(wg+1,wg+n+1,cmp);for(ll i=1;i<=n;i++)f[i][1]=wq[i],g[i][1]=wg[i];for(ll i=1;i<=n;i++){for(ll j=2;j<=i;j++){sum1[j-1]=(sum1[j-1]+f[i-1][j-1])%mod;f[i][j]=wq[i]*sum1[j-1]%mod;sum2[j-1]=(sum2[j-1]+g[i-1][j-1])%mod;g[i][j]=(C[i-1][j-1]*wg[i]+(sum2[j-1]))%mod;}} /* for(ll i=1;i<=n;i++)for(ll j=1;j<=i;j++)printf("f[%lld][%lld]=%lld g[%lld][%lld]=%lld\n",i,j,f[i][j],i,j,g[i][j]); */} inline void work(){ll ans=0;for(ll i=min(n,m);i>=0;i--){if(i<k)ans=(ans+F(i,i)*G(m-i,k-i)%mod)%mod/*,printf("F=%lld G=%lld\n",F(i,i),G(m-i,k-i))*/;else ans=(ans+F(i,k-1)*G(m-i,1)%mod)%mod/*,printf("F=%lld G=%lld\n",F(i,k-1),G(m-i,1))*/; // printf("ans=%lld\n",ans); }printf("%lld\n",ans); } int main() {for(ll i=0;i<=3000;i++)C[i][0]=1;for(ll i=1;i<=3000;i++)for(ll j=1;j<=i;j++)C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;t=read();while(t--){re();init();work();} }?
轉(zhuǎn)載于:https://www.cnblogs.com/znsbc-13/p/11238425.html
總結(jié)
以上是生活随笔為你收集整理的「PKUWC2018」Slay the Spire的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: linux系统分为哪几类?
- 下一篇: 一个iOS表单框架-UFKit