欢迎访问 生活随笔!

生活随笔

当前位置: 首页 >

jzoj6344-[NOIP2019模拟2019.9.7]Huge Counting【组合数,状压dp】

发布时间:2023/12/3 38 豆豆
生活随笔 收集整理的这篇文章主要介绍了 jzoj6344-[NOIP2019模拟2019.9.7]Huge Counting【组合数,状压dp】 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

正题


题目大意

定义函数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=1nf(x1...,xj1,...xn))%2
给出li,ril_i,r_ili,ri,求∑li≤xi≤rif(x)\sum_{l_i\leq x_i\leq r_i} f(x)lixirif(x)


解题思路

我们发现对于xxxf(x)=∏i=1n−1C∑xjxif(x)=\prod_{i=1}^{n-1}C_{\sum x_j}^{x_i}f(x)=i=1n1Cxjxi
然后又有CnkC_{n}^kCnk为奇数仅当(n+k)&k=k(n+k)\&k=k(n+k)&k=k
然后转换为f(x)=1f(x)=1f(x)=1的充要条件就是对于任意的1≤i≠j≤n1\leq i\neq j\leq n1i̸=jn(xi+xj)&xi=xi(x_i+x_j)\& x_i=x_i(xi+xj)&xi=xi,证明

然后我们数位dpdpdp,用fi,jf_{i,j}fi,j表示到第iii位时状态jjj中0表示没有到达上界,111表示到达了上界。

对于lil_ili,我们可以对nnn维进行容斥即可。

时间复杂度O(50∗n∗(2n)2)O(50*n*(2^n)^2)O(50n(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);} } 创作挑战赛新人创作奖励来咯,坚持创作打卡瓜分现金大奖

总结

以上是生活随笔为你收集整理的jzoj6344-[NOIP2019模拟2019.9.7]Huge Counting【组合数,状压dp】的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。