jzoj6344-[NOIP2019模拟2019.9.7]Huge Counting【组合数,状压dp】
正題
題目大意
定義函數(shù)f(x)(xf(x)(xf(x)(x為一個序列)))
若任意一個xi=1x_i=1xi?=1那么有f(x)=1f(x)=1f(x)=1
若有一個xi=0x_i=0xi?=0那么有f(x)=0f(x)=0f(x)=0
其他的,有f(x)=(∑j=1nf(x1...,xj?1,...xn))%2f(x)=(\sum_{j=1}^nf(x_{1}...,x_j-1,...x_n))\% 2f(x)=(j=1∑n?f(x1?...,xj??1,...xn?))%2
給出li,ril_i,r_ili?,ri?,求∑li≤xi≤rif(x)\sum_{l_i\leq x_i\leq r_i} f(x)li?≤xi?≤ri?∑?f(x)
解題思路
我們發(fā)現(xiàn)對于xxx有f(x)=∏i=1n?1C∑xjxif(x)=\prod_{i=1}^{n-1}C_{\sum x_j}^{x_i}f(x)=∏i=1n?1?C∑xj?xi??
然后又有CnkC_{n}^kCnk?為奇數(shù)僅當(dāng)(n+k)&k=k(n+k)\&k=k(n+k)&k=k
然后轉(zhuǎn)換為f(x)=1f(x)=1f(x)=1的充要條件就是對于任意的1≤i≠j≤n1\leq i\neq j\leq n1≤i??=j≤n有(xi+xj)&xi=xi(x_i+x_j)\& x_i=x_i(xi?+xj?)&xi?=xi?,證明
然后我們數(shù)位dpdpdp,用fi,jf_{i,j}fi,j?表示到第iii位時狀態(tài)jjj中0表示沒有到達(dá)上界,111表示到達(dá)了上界。
對于lil_ili?,我們可以對nnn維進(jìn)行容斥即可。
時間復(fù)雜度O(50?n?(2n)2)O(50*n*(2^n)^2)O(50?n?(2n)2)
codecodecode
#include<cstdio> #include<cstring> #include<algorithm> #define ll long long using namespace std; const ll N=10,XJQ=990804011; ll T,n,l[N],r[N],x[N],f[60][1<<N],ans,MS; ll solve(ll S) {for(ll i=0;i<n;i++){x[i]=((S>>i)&1)?(l[i]-1):r[i];if(x[i]<0) return 0;}memset(f,0,sizeof(f));f[51][0]=1;for(ll i=50;i>=0;i--){for(ll j=0;j<MS;j++){if(!f[i+1][j]) continue;ll now=0;for(ll k=0;k<n;k++)now|=(1<<k)*(x[k]>>i&1);(f[i][j|now]+=(__builtin_popcount(j)+1)*f[i+1][j]+XJQ)%=XJQ;for(ll k=0;k<n;k++)if((now&(~j))>>k&1)(f[i][j|(now^(1<<k))]+=f[i+1][j]+XJQ)%=XJQ;}}ll ans=0;for(ll i=0;i<MS;i++)(ans+=f[0][i]+XJQ)%=XJQ;return ans; } int main() {freopen("c.in","r",stdin);freopen("c.out","w",stdout);scanf("%lld",&T);while(T--){scanf("%lld",&n);MS=1<<n;ans=0;for(ll i=0;i<n;i++)scanf("%lld%lld",&l[i],&r[i]),l[i]--,r[i]--;for(ll i=0;i<MS;i++)(ans+=(__builtin_popcount(i)&1?XJQ-solve(i):solve(i))+XJQ)%=XJQ;printf("%lld\n",ans);} } 創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎總結(jié)
以上是生活随笔為你收集整理的jzoj6344-[NOIP2019模拟2019.9.7]Huge Counting【组合数,状压dp】的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: en是什么意思 en解释
- 下一篇: 牛客小白月赛17-记录(附题解)