nssl1323,jzoj(初中)2107-交流【dfs,容斥,组合数】
生活随笔
收集整理的這篇文章主要介紹了
nssl1323,jzoj(初中)2107-交流【dfs,容斥,组合数】
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
正題
題目大意
對于mmm個字符串,一些地方是???表示可以填任意字符。
每一個目標串要滿足至少kkk個串。
求方案總數。
解題思路
首先暴力搜索一些串選擇或不選擇,然后容斥。
選擇之后我們可以得出一個串KKK我們稱之為最終串,這時我們可以統計滿足這個最終串的字符串個數。
然后我們考慮容斥,定義sumksum_ksumk?表示選擇kkk個串的時候的方案總數之和。
那么答案就是∑i=kmsumi?Cmi?k?((i?k)%2??1:1)\sum_{i=k}^msum_i*C_m^{i-k}*((i-k)\%2\ ?\ -1:1)i=k∑m?sumi??Cmi?k??((i?k)%2????1:1)
首先那個1,?11,-11,?1是容斥,然后考慮組合數的原理。
例子:{a??}{?a?}{??a}(k=2)\{a??\}\{?a?\}\{??a\}(k=2){a??}{?a?}{??a}(k=2)
這時我們發現三個串都選擇時的aaaaaaaaa被多選擇了3次,而這3次就是在mmm個字串中選擇222個字串時方案數。
codecodecode
#include<cstdio> #include<algorithm> #include<cstring> using namespace std; const int L=55,XJQ=1000003; int m,K,l,ans,C[L]; char k[L],y[20][L]; void dfs(int dep,int c) {if(dep>m){if(c<K) return;int w=1;for(int i=1;i<=l;i++)if(k[i]=='?') w=w*26%XJQ;ans=(ans+w*C[c-K]*(((c-K)&1)?-1:1)+XJQ)%XJQ;return;}char b[L];bool flag=1;for(int i=1;i<=l;i++){if(k[i]!='?'&&y[dep][i]!='?'&&k[i]!=y[dep][i])flag=0;b[i]=k[i];k[i]=(y[dep][i]=='?'?k[i]:y[dep][i]);}if(flag) dfs(dep+1,c+1);for(int i=1;i<=l;i++)k[i]=b[i];dfs(dep+1,c); } int main() {scanf("%d%d",&m,&K);C[0]=1;for(int i=1;i<=m-K;i++)C[i]=C[i-1]*(K+i)/i%XJQ;for(int i=1;i<=m;i++)scanf("%s",y[i]+1);l=strlen(y[1]+1);for(int i=1;i<=l;i++)k[i]='?';dfs(1,0);printf("%d",ans); }總結
以上是生活随笔為你收集整理的nssl1323,jzoj(初中)2107-交流【dfs,容斥,组合数】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怎么样在旧电脑上安装Windows11w
- 下一篇: 欢乐SSL初二组周六赛【2019.5.1