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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

[XSY] 简单的博弈题(博弈+dp+组合数+容斥)

發布時間:2023/12/3 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [XSY] 简单的博弈题(博弈+dp+组合数+容斥) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

簡單的博弈題
對于貪心的對手,顯然用最大的一半和他最小的一半比較判斷是否全勝。(這不就是田忌賽馬嗎)

對于隨機的對手,先考慮暴力怎么做:

void check(int x,int w){if(x>m){res+=(w>=m/2+1);return;}for(int i=1;i<=m;i++){if(visb[i]) continue;visb[i]=1;if(xa[x]>b[i]) check(x+1,w+1);else check(x+1,w);visb[i]=0;} } void dfs(int x){if(x>m){res=0;check(1,0);ans=max(ans,res);return;}for(int i=1;i<=m;i++){if(visa[i]) continue;visa[i]=1;xa[x]=a[i];dfs(x+1);visa[i]=0;} } int main(){inv[0]=inv[1]=1;for(int i=2;i<N;i++) inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;for(int i=1;i<N;i++) inv[i]=1ll*inv[i-1]*inv[i]%mod;scanf("%d%d",&n,&m);for(int i=1;i<=m;i++)scanf("%lld",&a[i]);while(n--){scanf("%d",&op);for(int i=1;i<=m;i++) scanf("%lld",&b[i]);ans=0;dfs(1);ans=ans*inv[m]%mod;printf("%lld\n",ans);} }

由暴力中我們發現一件事:由于a[],b[]a[],b[]a[],b[]的配對情況固定,第一個人使用任何策略都不影響他獲勝的概率\color{Red}第一個人使用任何策略都不影響他獲勝的概率使
也就是說我們只需選一種自己數字的排列并固定下來,再去和對手的數字的m!m!m!種全排列匹配即可。

暴力枚舉全排列顯然是不可接受的,考慮從小到大考慮自己的每個數,用fi,jf_{i,j}fi,j?表示考慮了前iii小的數,給其中jjj個匹配了比他小的數字的方案數

思考fi,jf_{i,j}fi,j?的轉移:
若給第iii個數匹配比他小的數字:
fi,j←fi?1,j?1×(p?(j?1))f_{i,j}\leftarrow f_{i-1,j-1}\times(p-(j-1))fi,j?fi?1,j?1?×(p?(j?1))
(其中ppp表示對手的數字中有ppp個小于a[i]a[i]a[i]
若給第iii個數匹配比他大的數字:
fi,j←fi?1,j×qf_{i,j}\leftarrow f_{i-1,j}\times qfi,j?fi?1,j?×q
(其中qqq表示此時對手的數字中還剩qqq個比a[i]a[i]a[i]大的未匹配)

問題來了,要算出qqq,必須知道前i?1i-1i?1個數具體匹配了對手的哪些數,那不就跟暴力一樣了嗎?

對此,我們的解決方法是
若不給第iii個數匹配比他小的數字,那么這個數先不匹配,即fi,j=fi?1,j+fi?1,j?1×(p?(j?1))f_{i,j}=f_{i-1,j}+f_{i-1,j-1}\times(p-(j-1))fi,j?=fi?1,j?+fi?1,j?1?×(p?(j?1))
在考慮完自己的所有數后,我們再給還沒匹配的數統一匹配:
fm,j=fm,j×(m?j)!f_{m,j}=f_{m,j}\times(m-j)!fm,j?=fm,j?×(m?j)!
但這樣我們就不能保證所有數中恰好\color{Blue}恰好jjj個數匹配到了比他小的數,事實上,fm,j表示所有數中\color{Red}f_{m,j}表示所有數中fm,j?至少\color{Blue}至少有j個數匹配到了比他小的數的方案數\color{Red}有j個數匹配到了比他小的數\space的方案數j?

根據廣義容斥原理/二項式反演
g(k)g(k)g(k)表示所有數中恰好kkk個數匹配到了比他小的數 的方案數,
f(k)f(k)f(k)表示所有數中至少kkk個數匹配到了比他小的數 的方案數,
ans表示自己能贏的方案數ans表示自己能贏的方案數ans
∵f(k)=∑i=kmCikg(i)\because f(k)=\sum_{i=k}^{m}C_{i}^{k}g(i)f(k)=i=km?Cik?g(i) (因此ans=?f(?m+12?))\color{Red}(因此ans\not=f(\left\lfloor\frac{m+1}{2}\right\rfloor))ans?=f(?2m+1??)
∴g(k)=∑i=km(?1)i?kCikf(i)\therefore g(k)=\sum_{i=k}^{m}(-1)^{i-k}C_{i}^{k}f(i)g(k)=i=km?(?1)i?kCik?f(i)

w=?m+12?w=\left\lfloor\frac{m+1}{2}\right\rfloorw=?2m+1??
ans=∑k=wmg(k)=∑k=wm∑i=km(?1)i?kCikf(i)=∑i=wmf(i)∑k=wi(?1)i?kCikans=\sum_{k=w}^{m}g(k)=\sum_{k=w}^{m}\sum_{i=k}^{m}(-1)^{i-k}C_{i}^{k}f(i)=\color{Red}\sum_{i=w}^{m}f(i)\sum_{k=w}^{i}(-1)^{i-k}C_{i}^{k}ans=k=wm?g(k)=k=wm?i=km?(?1)i?kCik?f(i)=i=wm?f(i)k=wi?(?1)i?kCik?
事實上,優化到這里已經能AC了

但這個式子還可以再優化:
引理1:∑i=wn(?1)n?iCni=(?1)n?wCn?1w?1\color{Red}\sum_{i=w}^{n}(-1)^{n-i}C_{n}^{i}=(-1)^{n-w}C_{n-1}^{w-1}i=wn?(?1)n?iCni?=(?1)n?wCn?1w?1?
證明1:

引理2:Cni=Cn?1i?1+Cn?1iC_{n}^{i}=C_{n-1}^{i-1}+C_{n-1}^{i}Cni?=Cn?1i?1?+Cn?1i?
證明2:顯然

由引理2,Cn?1i?1=Cni?Cn?1iC_{n-1}^{i-1}=C_{n}^{i}-C_{n-1}^{i}Cn?1i?1?=Cni??Cn?1i?
∵Cni+1=Cn?1i+Cn?1i+1\because C_{n}^{i+1}=C_{n-1}^{i}+C_{n-1}^{i+1}Cni+1?=Cn?1i?+Cn?1i+1?
∴Cn?1i=Cni+1?Cn?1i+1\therefore C_{n-1}^{i}=C_{n}^{i+1}-C_{n-1}^{i+1}Cn?1i?=Cni+1??Cn?1i+1?
∴Cn?1i?1=Cni?(Cni+1?Cn?1i+1)=Cni?Cni+1+Cn?1i+1\therefore C_{n-1}^{i-1}=C_{n}^{i}-(C_{n}^{i+1}-C_{n-1}^{i+1})=C_{n}^{i}-C_{n}^{i+1}+C_{n-1}^{i+1}Cn?1i?1?=Cni??(Cni+1??Cn?1i+1?)=Cni??Cni+1?+Cn?1i+1?
pi?1=Cn?1i?1p_{i-1}=C_{n-1}^{i-1}pi?1?=Cn?1i?1?,那么
pi?1=Cni?Cni+1+Cn?1i+1=Cni?Cni+1+pi+1p_{i-1}=C_{n}^{i}-C_{n}^{i+1}+C_{n-1}^{i+1}=C_{n}^{i}-C_{n}^{i+1}+p_{i+1}pi?1?=Cni??Cni+1?+Cn?1i+1?=Cni??Cni+1?+pi+1?
∵pi+1=Cni+2?Cni+3+pi+3\because p_{i+1}=C_{n}^{i+2}-C_{n}^{i+3}+p_{i+3}pi+1?=Cni+2??Cni+3?+pi+3?
∴pi?1=Cni?Cni+1+Cni+2?Cni+3+pi+3=Cni?Cni+1+Cni+2?Cni+3+Cni+4?Cni+5+...Cnn\therefore p_{i-1}=C_{n}^{i}-C_{n}^{i+1}+C_{n}^{i+2}-C_{n}^{i+3}+p_{i+3}=C_{n}^{i}-C_{n}^{i+1}+C_{n}^{i+2}-C_{n}^{i+3}+C_{n}^{i+4}-C_{n}^{i+5}+...C_{n}^{n}pi?1?=Cni??Cni+1?+Cni+2??Cni+3?+pi+3?=Cni??Cni+1?+Cni+2??Cni+3?+Cni+4??Cni+5?+...Cnn?
∴∑i=wn(?1)n?iCni=(?1)n?wpw?1=(?1)n?wCn?1w?1\therefore \sum_{i=w}^{n}(-1)^{n-i}C_{n}^{i}=(-1)^{n-w}p_{w-1}=(-1)^{n-w}C_{n-1}^{w-1}i=wn?(?1)n?iCni?=(?1)n?wpw?1?=(?1)n?wCn?1w?1?
證畢

∴ans=∑i=wmf(i)∑k=wi(?1)i?kCik=∑i=wm(?1)i?wCi?1w?1f(i)\therefore ans=\sum_{i=w}^{m}f(i)\sum_{k=w}^{i}(-1)^{i-k}C_{i}^{k}=\sum_{i=w}^{m}(-1)^{i-w}C_{i-1}^{w-1}f(i)ans=i=wm?f(i)k=wi?(?1)i?kCik?=i=wm?(?1)i?wCi?1w?1?f(i)

#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=10010; const int mod=998244353; int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f; } int f[N],a[N],b[N],fac[N],inv[N]; int power(int a,int b){int res=1;while(b){if(b&1) res=1ll*res*a%mod;a=1ll*a*a%mod;b>>=1;}return res; } void init(int n){fac[0]=1;for(int i=1;i<=n;i++) fac[i]=1ll*fac[i-1]*i%mod;inv[n]=power(fac[n],mod-2);for(int i=n;i>=1;i--) inv[i-1]=1ll*inv[i]*i%mod; } int C(int n,int m){return 1ll*fac[n]*inv[m]%mod*inv[n-m]%mod; } int n,m,op; int main(){scanf("%d%d",&n,&m);for(int i=1;i<=m;i++) a[i]=read();sort(a+1,a+m+1);init(m);while(n--){scanf("%d",&op);for(int i=1;i<=m;i++) b[i]=read();sort(b+1,b+m+1);if(op==1){int ans=1;for(int i=1;i<=(m+1)/2;i++){if(b[i]>a[i+(m-1)/2]){ans=0;break;}}printf("%d\n",ans);} else{memset(f,0,sizeof(f));f[0]=1;for(int i=1;i<=m;i++){int p=lower_bound(b+1,b+m+1,a[i])-b-1;for(int j=p;j>=1;j--)f[j]=(f[j]+1ll*f[j-1]*(p-(j-1)))%mod;}for(int i=1;i<=m;i++)f[i]=1ll*f[i]*fac[m-i]%mod;int ans=0,tag=0;for(int i=(m+1)/2;i<=m;i++){int sum=1ll*C(i-1,(m-1)/2)*f[i]%mod;if(tag) sum=mod-sum;ans=(ans+sum)%mod;tag^=1;}ans=1ll*ans*inv[m]%mod;printf("%lld\n",ans);}}return 0; }

總結

以上是生活随笔為你收集整理的[XSY] 简单的博弈题(博弈+dp+组合数+容斥)的全部內容,希望文章能夠幫你解決所遇到的問題。

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