Description

有一个 n 行 m 列的表格,行从 0 到 n−1 编号,列从 0 到 m−1 编号。每个格子都储存着能量。最初,第 i 行第 j 列的格子储存着 (i xor j) 点能量。所以,整个表格储存的总能量是,

随着时间的推移,格子中的能量会渐渐减少。一个时间单位,每个格子中的能量都会减少 1。显然,一个格子的能量减少到 0 之后就不会再减少了。
也就是说,k 个时间单位后,整个表格储存的总能量是,
给出一个表格,求 k 个时间单位后它储存的总能量。
由于总能量可能较大,输出时对 p 取模。

Input

第一行一个整数 T,表示数据组数。接下来 T 行,每行四个整数 n、m、k、p。

 

Output

共 T 行,每行一个数,表示总能量对 p 取模后的结果

 

Sample Input

3
2 2 0 100
3 3 0 100
3 3 1 100

Sample Output

2
12
6

HINT

T=5000,n≤10^18,m≤10^18,k≤10^18,p≤10^9

 
好恶心的数位DP,先将三个串二进制拆分,然后设g[len][S]表示前len位状态为S的方案数,f[len][S]表示前len位状态为S的(i xor j)-k的结果。
S包括i与n的大小关系,j与m的大小关系,i xor j与k的大小关系,然后使劲讨论就行了。
 
#include<cstdio>
#include<cctype>
#include<queue>
#include<cstring>
#include<algorithm>
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define ren for(int i=first[x];i;i=next[i])
using namespace std;
const int BufferSize=1<<16;
char buffer[BufferSize],*head,*tail;
inline char Getchar() {
if(head==tail) {
int l=fread(buffer,1,BufferSize,stdin);
tail=(head=buffer)+l;
}
return *head++;
}
typedef long long ll;
inline ll read() {
ll x=0,f=1;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*f;
}
ll xp[70],f[70][2][2][2],g[70][2][2][2],n,m,k;
//c1=1 -> x<n c2=1 -> y<m c3=1 -> x^y>k
int p,bitn[70],lenn,bitm[70],lenm,bitk[70],lenk;
void solve() {
memset(bitn,0,sizeof(bitn));
memset(bitm,0,sizeof(bitm));
memset(bitk,0,sizeof(bitk));
memset(f,0,sizeof(f));
memset(g,0,sizeof(g));
lenn=lenm=lenk=0;
while(n) bitn[lenn++]=n&1,n>>=1;
while(m) bitm[lenm++]=m&1,m>>=1;
while(k) bitk[lenk++]=k&1,k>>=1;
int len=max(lenn,max(lenm,lenk));
xp[0]=1;rep(i,1,len) xp[i]=(xp[i-1]*2)%p;
rep(c1,0,1) rep(c2,0,1) rep(c3,0,1) {
ll &ans=f[0][c1][c2][c3],&ans2=g[0][c1][c2][c3];
rep(x,0,(c1?1:bitn[0]-1)) rep(y,0,(c2?1:bitm[0]-1)) {
if((x^y)>=bitk[0]) (ans+=((x^y)-bitk[0]))%=p,ans2++;
else if(c3) (ans+=((x^y)-bitk[0]))%=p,ans2++;
}
}
rep(i,1,len-1) rep(c1,0,1) rep(c2,0,1) rep(c3,0,1) {
ll &ans=f[i][c1][c2][c3],&ans2=g[i][c1][c2][c3];
rep(x,0,max(bitn[i],c1)) rep(y,0,max(bitm[i],c2)) {
if((x^y)>=bitk[i]) {
(ans+=f[i-1][c1|(x<bitn[i])][c2|(y<bitm[i])][c3|((x^y)>bitk[i])]+g[i-1][c1|(x<bitn[i])][c2|(y<bitm[i])][c3|((x^y)>bitk[i])]*((x^y)-bitk[i])*xp[i])%=p;
(ans2+=g[i-1][c1|(x<bitn[i])][c2|(y<bitm[i])][c3|((x^y)>bitk[i])])%=p;
}
else if(c3) {
(ans+=f[i-1][c1|(x<bitn[i])][c2|(y<bitm[i])][c3|((x^y)>bitk[i])]+g[i-1][c1|(x<bitn[i])][c2|(y<bitm[i])][c3|((x^y)>bitk[i])]*((x^y)-bitk[i])*xp[i])%=p;
(ans2+=g[i-1][c1|(x<bitn[i])][c2|(y<bitm[i])][c3|((x^y)>bitk[i])])%=p;
}
}
}
printf("%lld\n",(f[len-1][0][0][0]+p)%p);
}
int main() {
dwn(T,read(),1) {
n=read();m=read();k=read();p=read();
solve();
}
return 0;
}

  

BZOJ4513: [Sdoi2016]储能表的更多相关文章

  1. BZOJ4513 SDOI2016 储能表 记忆化搜索(动态规划)

    题意: 题面中文,不予翻译:SDOI2016储能表 分析: 据说有大爷用一些奇怪的方法切掉了这道题%%%%% 这里用的是大众方法——动态规划. 其实这是一道类似于二进制数位dp的动态规划题,(但是实际 ...

  2. BZOJ4513 SDOI2016储能表(数位dp)

    如果n.m.k都是2的幂次方,答案非常好统计.于是容易想到数位dp,考虑每一位是否卡限制即可,即设f[i][0/1][0/1][0/1]为第i位是/否卡n.m.k的限制时,之前的位的总贡献:g[i][ ...

  3. bzoj千题计划277:bzoj4513: [Sdoi2016]储能表

    http://www.lydsy.com/JudgeOnline/problem.php?id=4513 f[i][0/1][0/1][0/1] 从高到低第i位,是否卡n的上限,是否卡m的上限,是否卡 ...

  4. BZOJ4513: [Sdoi2016]储能表(数位dp)

    题意 题目链接 Sol 一点思路都没有,只会暴力,没想到标算是数位dp??Orz 首先答案可以分成两部分来统计 设 \[ f_{i,j}= \begin{aligned} i\oplus j & ...

  5. [bzoj4513][SDOI2016]储能表——数位dp

    题目大意 求 \[\sum_{i = 0}^{n-1}\sum_{j=0}^{m-1} max((i\ xor\ j)\ -\ k,\ 0)\ mod\ p\] 题解 首先,开始并没有看出来这是数位d ...

  6. 【BZOJ4513】[Sdoi2016]储能表 数位DP

    [BZOJ4513][Sdoi2016]储能表 Description 有一个 n 行 m 列的表格,行从 0 到 n−1 编号,列从 0 到 m−1 编号.每个格子都储存着能量.最初,第 i 行第 ...

  7. BZOJ 4513: [Sdoi2016]储能表 [数位DP !]

    4513: [Sdoi2016]储能表 题意:求\[ \sum_{i=0}^{n-1}\sum_{j=0}^{m-1} max((i\oplus j)-k,0) \] 写出来好开心啊...虽然思路不完 ...

  8. 4513: [Sdoi2016]储能表

    4513: [Sdoi2016]储能表 链接 分析: 数位dp. 横坐标和纵坐标一起数位dp,分别记录当前横纵坐标中这一位是否受n或m的限制,在记录一维表示当前是否已经大于k了. 然后需要两个数组记录 ...

  9. 【LG4067】[SDOI2016]储能表

    [LG4067][SDOI2016]储能表 题面 洛谷 题解 这种$n$.$m$出奇的大的题目一看就是数位$dp$啦 其实就是用一下数位$dp$的套路 设$f[o][n][m][k]$表示当前做到第$ ...

随机推荐

  1. 【翻译十三】java-并发之饥饿与活锁

    Starvation and Livelock Starvation and livelock are much less common a problem than deadlock, but ar ...

  2. sdut 1592转置矩阵【稀疏矩阵的压缩存储】【快速转置算法】

    转置矩阵 Time Limit: 1000ms   Memory limit: 32768K  有疑问?点这里^_^ 题目链接:http://acm.sdut.edu.cn/sdutoj/proble ...

  3. Java代码实现excel数据导入到Oracle

    1.首先需要两个jar包jxl.jar,ojdbc.jar(注意版本,版本不合适会报版本错误)2.代码: Java代码   import java.io.File; import java.io.Fi ...

  4. oracle删除用户下所有的表

    需要创建这些删除语句,通过oracle的数据字典找到该用户下的所有表.视图等对象,拼接成语句.如下select 'drop table '||table_name|| ' cascade constr ...

  5. [Java][Weblogic] weblogic.net.http.SOAPHttpsURLConnection incompatible with javax.net.ssl.HttpsURLConnection解决办法

    更新20141120: 我始终对修改生产上weblogic上的配置文件这一方法心存担忧(生产上的服务器不允许随便修改,可能会影响到其他应用),所以想使用代码的方式解决此问题,在对方法一失败原因进行了进 ...

  6. 在Virtulbox上装Ubuntu

    做个程序员,会用Linux,这应该是最基本的要求吧.可惜本人经常用Windows,只是偶尔去服务器上做些操作的时候才接触到linux.so,我要学Linux.刚学所以还是先装个虚拟机吧,等在虚拟机上用 ...

  7. 提高Axure设计效率的10条建议 (转)

    Axure 是创建软件原型的快速有力的工具.上手很容易,但是,其中存在一个危险.这款软件是如此的直观以至于很多用户可以在没有接受过任何正式培训的情况下进行使用.他们可能不知道的是他们可能没有以恰当的方 ...

  8. 用JAXP的SAX方式解析XML文件

    简单用JAXP的SAX方式(事件驱动)解析XML文件: 文件(1.XML) <?xml version="1.0" encoding="UTF-8" st ...

  9. Angular.js 以及个人学习网站

    Angular.js  教程 http://www.360doc.com/content/14/0414/15/14416931_368816305.shtml web前端学习: 慕课网:http:/ ...

  10. Codeforces Round #375 (Div. 2) - C

    题目链接:http://codeforces.com/contest/723/problem/C 题意:给定长度为n的一个序列.还有一个m.现在可以改变序列的一些数.使得序列里面数字[1,m]出现次数 ...