zoukankan      html  css  js  c++  java
  • [SDOI2016]储能表

    题目

    数位(dp)思博题啊

    但是我更加思博啊

    面对(10^{18})的数据范围,我竟然只开了(19)的数据,而这是一道二进制数位(dp)

    我们设(f[i][0/1][0/1][0/1])表示进行到了第(i)位,不卡/卡(n)的上界,不卡/卡(m)的上界,不卡/卡(k)的下界,我们求出所有异或值大于(k)的数的和,和方案数随便搞一搞就出来了

    代码

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #define re register
    #define LL long long
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)<(b)?(a):(b))
    inline LL read() {
    	char c=getchar();LL x=0;while(c<'0'||c>'9') c=getchar();
    	while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
    }
    int T;
    LL n,m,K,mod;
    LL dp[67][2][2][2],f[67][2][2][2],pw[67];
    int a[67],b[67],c[67];
    inline void countBit(LL x,int *g) {
    	int tot=0;
    	while(x) {g[tot++]=(x&1ll);x>>=1ll;}
    }
    int main() {
    	T=read();
    	while(T--) {
    		n=read(),m=read(),K=read(),mod=read();
    		if(n>m) std::swap(n,m);
    		n--,m--;
    		memset(dp,0,sizeof(dp));
    		memset(f,0,sizeof(f));
    		memset(a,0,sizeof(a));
    		memset(b,0,sizeof(b));
    		memset(c,0,sizeof(c));
    		memset(pw,0,sizeof(pw));
    		pw[0]=1;
    		for(re int i=1;i<=65;i++) pw[i]=(pw[i-1]+pw[i-1])%mod;
    		countBit(n,a),countBit(m,b),countBit(K,c);
    		f[66][1][1][1]=1;
    		for(re int i=65;i>=0;--i)
    			for(re int j=0;j<2;j++)
    				for(re int k=0;k<2;k++)
    					for(re int p=0;p<2;p++) {
    						for(re int t=0;t<2;t++)
    							for(re int h=0;h<2;h++) {
    								if(j&&t>a[i]) continue;
    								if(k&&h>b[i]) continue;
    								if(p&&(t^h)<c[i]) continue;
    								int o1=j;
    								if(o1) if(t<a[i]) o1=0;
    								int o2=k;
    								if(o2) if(h<b[i]) o2=0;
    								int o3=p;
    								if(o3) if((t^h)>c[i]) o3=0;
    								f[i][o1][o2][o3]=(f[i][o1][o2][o3]+f[i+1][j][k][p])%mod;
    								dp[i][o1][o2][o3]=(dp[i][o1][o2][o3]+dp[i+1][j][k][p])%mod;
    								if(h^t) 
    									dp[i][o1][o2][o3]=(dp[i][o1][o2][o3]+f[i+1][j][k][p]*pw[i]%mod)%mod;
    							}
    					}
    		LL ans=0,cnt=0;
    		for(re int i=0;i<2;i++)
    			for(re int j=0;j<2;j++)
    				for(re int k=0;k<2;k++)
    					ans=(ans+dp[0][i][j][k])%mod,cnt=(cnt+f[0][i][j][k])%mod;
    		K%=mod;
    		printf("%lld
    ",(ans-cnt*K%mod+mod)%mod);	
    	}
    	return 0;
    }
    
  • 相关阅读:
    pythonday06数据类型(四)
    pythonday05数据类型(三)
    pythonday04数据类型(二)
    pythonday03数据类型(一)
    Apollo自动驾驶实践——第0讲:导论
    图论学习:生成树的Matrix-tree定理
    2020杭电多校6 Expectation
    2020牛客暑期多校第九场 B Groundhog and Apple Tree
    图论:二分图最大权匹配KM算法
    第十章 百度Apollo实战
  • 原文地址:https://www.cnblogs.com/asuldb/p/10633441.html
Copyright © 2011-2022 走看看