日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

「PKUWC2018」Slay the Spire

發布時間:2023/12/2 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 「PKUWC2018」Slay the Spire 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

國際慣例不放題干

扯淡

其實題目翻譯過來是殺戮尖塔,某steam上的卡牌游戲,我也曾熱衷刷榜

題解

首先題目中要求的期望是假期望,結合題目中所給的階乘就可以看出這其實是從$2*n$張牌中選擇$m$張牌使用,并且所有情況都取最大值時的和

首先排序貪心最大

再說一個非常顯然的結論,有強化牌就用,強化牌上數大于2,所以打出強化牌一定收益>=比打出一張攻擊牌帶來(保證最后一定要出至少一張攻擊牌就行)

例如? 你有強化牌? 2 2 攻擊牌 4 4 限制出2張

那么你先打一張2再打一張4和 先打4 再打4 收益一樣 ?

那么如果強化牌比k張要小,那么要把所有強化牌都用了,最后打輸出.如果強化牌比k還要大,那么最后留一張攻擊牌打出來就行了

我們可以假設$F(i,j)$表示你有i張強化牌時打出j張時收益,$G(i,j)$表示你有i張攻擊牌時打出j張時收益

那么最后答案就是

$\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)$

那么我們現在的任務就是快速求出來F和G

考慮直接求非常難求,我們這時一般要開幾個別的數組

首先開$f[i][j]$ $g[i][j]$表示當你抽到i張牌必打第i張一共打了j張時收益

那么可以推出來$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]$ (這里的組合數表示一共有$C_{i-1}^{j-1}$種方式轉移過來,每種轉移都要加一個w)

然后得到$F(i,j)=\sum_{l=j}^{n} C_{n-l}^{i-j} f[l][j]$

解釋一下 F可以從l中使用j張(這j張都是大牌)再從剩余n-l中選擇i-j張不打共同構成F的i張打了j張

G同理得到$G(i,j)=\sum{l=j}^{n} C_{n-l}^{i-j} g[i][j]$

然后轉移就完了

本題稍卡常

代碼

#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張選出j張再從n-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();} }

?

轉載于:https://www.cnblogs.com/znsbc-13/p/11238425.html

總結

以上是生活随笔為你收集整理的「PKUWC2018」Slay the Spire的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。