数位dp hdu5598 GTW likes czf
2015-12-14 01:38
309 查看
传送门:点击打开链接
题意:告诉l,r,g,t,每次在[l,r]区间内选一个数字,再从g,t这两个数字里面选一个数字,求这两个数字的@值。定义x@y=((x&y)|y)^x
思路:首先,我们能够证明,x@y=((x&y)|y)^x其实就等于x^y,这算是第一个绕圈把
然后呢,我们再考虑到,一个数x对n个不同的数字求位异或,那么位异或的结果一定都不同。
所以,题目可以转换成(r-l+1)*2-num,num是满足如下条件的a和b的对数
a,b属于[l,r], 且 a^g=b^t,我们稍微变形一下,就得到a^b=g^t
所以最后题目转换成了求[l,r]中有多少对(a,b),使得a^b=g^t
因为区间有左端,我们可以通过容斥进一步的简化题目。
设S(m,n)函数能求出a在区间[1,m],b在区间[1,n],然后a^b=g^t的对数
那么要求a在区间[l,r],b在区间[l,r],然后求a^b=g^t的个数就可以转换成S(r,r)-S(l-1,r)*2+S(l-1,l-1),原理是容斥定理,可以仔细去想想
到上面的步数,应该都是很容易就能看懂的,问题是S(m,n)函数要如何来实现
这里我们用数位dp来实现
那么对于S(a,b)
设dp
[i][j]表示正在考虑第n位bit位
i为0表示a的第n位没有被限制,1表示a的第n位被限制了
j为0表示b的第n位没有被限制,1表示b的第n位被限制了
那么动态转移方程就能写出来了,我的dp写的有点搓,不要在意这些细节...
题意:告诉l,r,g,t,每次在[l,r]区间内选一个数字,再从g,t这两个数字里面选一个数字,求这两个数字的@值。定义x@y=((x&y)|y)^x
思路:首先,我们能够证明,x@y=((x&y)|y)^x其实就等于x^y,这算是第一个绕圈把
然后呢,我们再考虑到,一个数x对n个不同的数字求位异或,那么位异或的结果一定都不同。
所以,题目可以转换成(r-l+1)*2-num,num是满足如下条件的a和b的对数
a,b属于[l,r], 且 a^g=b^t,我们稍微变形一下,就得到a^b=g^t
所以最后题目转换成了求[l,r]中有多少对(a,b),使得a^b=g^t
因为区间有左端,我们可以通过容斥进一步的简化题目。
设S(m,n)函数能求出a在区间[1,m],b在区间[1,n],然后a^b=g^t的对数
那么要求a在区间[l,r],b在区间[l,r],然后求a^b=g^t的个数就可以转换成S(r,r)-S(l-1,r)*2+S(l-1,l-1),原理是容斥定理,可以仔细去想想
到上面的步数,应该都是很容易就能看懂的,问题是S(m,n)函数要如何来实现
这里我们用数位dp来实现
那么对于S(a,b)
设dp
[i][j]表示正在考虑第n位bit位
i为0表示a的第n位没有被限制,1表示a的第n位被限制了
j为0表示b的第n位没有被限制,1表示b的第n位被限制了
那么动态转移方程就能写出来了,我的dp写的有点搓,不要在意这些细节...
#include<map> #include<set> #include<cmath> #include<ctime> #include<stack> #include<queue> #include<cstdio> #include<cctype> #include<string> #include<vector> #include<cstring> #include<iostream> #include<algorithm> #include<functional> #define fuck(x) cout<<"["<<x<<"]" #define FIN freopen("input.txt","r",stdin) #define FOUT freopen("output.txt","w+",stdout) using namespace std; typedef long long LL; const int MX = 100 + 5; const int mod = 1e9 + 7; int na[MX], nb[MX], nx[MX]; LL l, r, g, t, dp[MX][2][2]; LL S(LL a, LL b, LL x) { memset(dp, 0, sizeof(dp)); for(int i = 63; i >= 0; i--) { na[i] = a >> i & 1; nb[i] = b >> i & 1; nx[i] = x >> i & 1; } dp[63][1][1] = 1; for(int i = 62; i >= 0; i--) { if(na[i] ^ nb[i] == nx[i]) { dp[i][1][1] += dp[i + 1][1][1]; } dp[i][1][0] += dp[i + 1][1][0]; if(nb[i] && na[i] == nx[i]) dp[i][1][0] += dp[i + 1][1][1]; dp[i][0][1] += dp[i + 1][0][1]; if(na[i] && nb[i] == nx[i]) dp[i][0][1] += dp[i + 1][1][1]; dp[i][0][0] += dp[i + 1][0][0] * 2; if(na[i]) dp[i][0][0] += dp[i + 1][1][0]; if(nb[i]) dp[i][0][0] += dp[i + 1][0][1]; if(na[i] && nb[i] && !nx[i]) dp[i][0][0] += dp[i + 1][1][1]; } return dp[0][0][0] + dp[0][0][1] + dp[0][1][0] + dp[0][1][1]; } LL solve() { LL ret = (r - l + 1) * 2, x = g ^ t; ret -= S(r, r, x) - S(l - 1, r, x) * 2 + S(l - 1, l - 1, x); return ret % mod; } int main() { int T; //FIN; scanf("%d", &T); while(T--) { scanf("%I64d%I64d%I64d%I64d", &l, &r, &g, &t); printf("%I64d\n", solve()); } return 0; }
相关文章推荐
- YARN源码分析(一)-----ApplicationMaster
- 数据库下载
- iOS之UI--转场动画
- Storm系统架构以及代码结构学习
- LeetCode 206:Reverse Linked List
- mac下安装yaf
- Android基础常用日期操作工具类
- 【HTML+CSS】教你切图篇1-实现按钮
- 【JS】关于trim函数的小tips
- 退役了……
- 20135315宋宸宁信息安全系统设计基础期末总结
- 都是状态机
- 如何解决jquery版本冲突
- html5语义化标签
- MVC | 依赖注入 AutoFac (构造函数注入)
- STM32F4 开发笔记2: IO输出的设置
- 【NodeJs】NodeJs中base16转码
- HttpURLConnection和HttpClient连接网络
- 获取指定数量素数.
- 10019---JavaScript--闭包