2019 牛客网 第七场 H pair
题目链接:https://ac.nowcoder.com/acm/contest/887/H
题意:
给定A,B,C问在[1,A]和[1,B]中有多少对x,y满足x&y>C或者x^y<C.
数据范围:1<=A,B,C<=1e9,测试用例 T<=100 .
思路:
根据题意本题可以用数位dp来解。
/* and 0&0=0; 0&1=0; 1&0=0; 1&1=1;
xor 0 ^ 0=0; 0 ^ 1=1; 1^ 0=1; 1^1=0; 3
3 4 2
4 5 2
7 8 5 5
7
31 1<=x<=a
1<=y<=b x&y>c x^y<c */ #include <iostream>
#include <bitset>
using namespace std;
int main()
{
int t;
cin>>t;
while(t--)
{
int a,b,c,ans=;
cin>>a>>b>>c;
for(int i=;i<=a;i++)
for(int j=;j<=b;j++)
{
if((i^j)<c)
{
ans++;
cout<<(i^j)<<" ";
bitset<> aa(i);
bitset<> bb(j);
bitset<> cc(i^j);
cout<<aa<<" "<<i<<endl;
cout<<bb<<" "<<j<<endl;
cout<<cc<<" "<<(i^j)<<endl<<endl;
}
}
cout<<ans<<endl;
}
return ;
}
/*
7 8 5
0 3 2 4 3 0 1 4 2 1 0 4 0 1 2 3 4 1 0 3 2 4 2 3 0 1 4 3 2 1 0 31 0 3 2 4 3 0 1 4 2 1 0 4 0 1 2 3 4 1 0 3 2 4 2 3 0 1 4 3 2 1 0 31 0 3 2 4 3 0 1 4 2 1 0 4 0 1 2 3 4 1 0 3 2 4 2 3 0 1 4 3 2 1 0 0 32 0 3 2 4 3 0 1 4 2 1 0 0 1 2 4 1 0 3 4 2 3 0 22 0 3 2 3 0 1 2 1 0 0 10 0 0 0 0 0 0 0 7 0 0 1 1 0 0 1 1 0 0 1 1 0 13 0 2 0 1 2 1 0 0 1 2 1 0 2 2 0 1 2 1 0 19 0 3 2 3 0 1 2 1 0 0 1 2 3 1 0 3 2 2 3 0 1 3 2 1 0 25 0 3 2 4 3 0 1 4 2 1 0 4 0 1 2 3 4 1 0 3 2 4 2 3 0 1 4 3 2 1 0 31 */
/*
00000001
00000001
0
00000010
00000010
0
00000010
00000011
1
00000011
00000010
1
00000011
00000011
0
00000100
00000100
0
00000100
00000101
1 7
*/ /*
00000001 00000010 0 3
00000001 00000100 0 5
00000001 00000011 1 2
00000010 00000001 0 3
00000010 00000100 0 6
00000011 00000100 0 7
00000011 00000001 1 2
*/ /*
x&y>c x^y<c 2
00000001 00000001 1 0
00000010 00000010 2 0
00000010 00000011 2 1
00000011 00000010 2 1
00000011 00000011 3 0 */
/*
/*
00000001 00000100 0 5
00000001 00000110 0 7
00000001 00000111 1 6
00000001 00001000 0 9
00000010 00000100 0 6
00000010 00000101 0 7
00000010 00000111 2 5
00000010 00001000 0 10
00000011 00000100 0 7
00000011 00000101 1 6
00000011 00000110 2 5
00000011 00001000 0 11
00000100 00000001 0 5
00000100 00000010 0 6
00000100 00000011 0 7
00000100 00001000 0 12
00000101 00000010 0 7
00000101 00000011 1 6
00000101 00001000 0 13
00000110 00000001 0 7
00000110 00000011 2 5
00000110 00001000 0 14
00000111 00000001 1 6
00000111 00000010 2 5
00000111 00001000 0 15
*/ /*
x&y>c x^y<c
00000001 00000001 1 0
00000001 00000010 0 3
00000001 00000011 1 2
00000001 00000101 1 4 00000010 00000001 0 3
00000010 00000010 2 0
00000010 00000011 2 1 00000010 00000110 2 4 00000011 00000001 1 2
00000011 00000010 2 1
00000011 00000011 3 0
00000011 00000111 3 4
00000100 00000100 4 0
00000100 00000101 4 1
00000100 00000110 4 2
00000100 00000111 4 3 00000101 00000001 1 4 00000101 00000100 4 1
00000101 00000101 5 0
00000101 00000110 4 3
00000101 00000111 5 2 00000110 00000010 2 4 00000110 00000100 4 2
00000110 00000101 4 3
00000110 00000110 6 0
00000110 00000111 6 1 00000111 00000011 3 4
00000111 00000100 4 3 00000111 00000101 5 2
00000111 00000110 6 1 00000111 00000111 7 0 */
*/
分析题意的代码
大佬的解析:
题意:给你 三个数A,B,C让你从 1~A内选择一个X,1~B内选择一个Y
找出<X,Y>的对数,使得 X&Y > C || X^Y < C
平常做的数位dp都是从一个区间内找数的个数,而现在是从两个区间找数对的对数,那就在之前的三维dp上多开两维,之前是枚举一个区间上限,现在改成两个区间上限,其他的和普通的数位dp一样
注意数位dp找到的是从0开始的 0 & Y 和 X&0 一定都小于C 不需要管
但是 0 ^ Y 和 X^0 当Y 和 X 小于C时 是满足的 所以结果还需要减去 ^运算 X 或 Y 为零时的情
原文链接:https://blog.csdn.net/Daxian911/article/details/99462695
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <map>
#include <vector>
#include <queue>
using namespace std;
#define ll long long
#define int long long
const int maxn=1e5+;
ll dp[][][][][];
int a[], b[],c[];
ll dfs1(int pos, int And, int Xor, int limit1, int limit2){
if(pos == -) {
if(And == || Xor == ) return ;
return ;
}
if(dp[pos][And][Xor][limit1][limit2] != -) return dp[pos][And][Xor][limit1][limit2];
int up1 = limit1 ? a[pos] : ;
int up2 = limit2 ? b[pos] : ;
ll ans = ;
for(int i = ; i <= up1; i++) {
for(int j = ; j <= up2; j++) {
int x = i & j, y = i ^ j;
int _and = And;
int _xor = Xor;
if(And == ) {
if(x > c[pos]) _and = ;
else if(x < c[pos]) _and = ;
}
if(Xor == ) {
if(y > c[pos]) _xor = ;
else if(y < c[pos]) _xor = ;
}
ans += dfs1(pos - , _and, _xor, (i == up1) && limit1, limit2 &&(j == up2));
}
}
dp[pos][And][Xor][limit1][limit2] = ans;
return ans;
}
signed main()
{
int T, A, B, C;
scanf("%lld", &T); while(T--) {
memset(dp, -, sizeof(dp));
scanf("%lld%lld%lld", &A, &B, &C);
int i = , j = , k = ;
int ans = min(C - , A) + min (C - , B) + ;
while(i < ) {
a[i++] = (A & ); A>>=;
}
while(j < ) {
b[j++] = (B & ); B>>=;
}
while(k < ) {
c[k++] = (C & ); C>>=;
}
printf("%lld\n", dfs1(,,,,) - ans);
}
return ;
}
大佬的代码,我直接复制了
另外一个大佬的代码解析:
思路:数位dp,定义一个dp[len][lim1][lim2][ok1][ok2][za][zb]。
len代表当前枚举的二进制位,lim1,lim2分别代表x和y的上限,
ok1代表对于x&y>C是否成立,成立是1,有可能成立是0,不可能成立是-1,
ok2代表对于x^y<C是否成立,1代表不成立,0代表可能成立,-1代表成立,
za和zb分别代表x和y的数中是否出现了1,因为x和y的二进制位不能是全零。转移的话代码中非常容易看懂。
原文链接:https://blog.csdn.net/qq_43316231/article/details/98968980
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int t;
ll A,B,C,f[],g[],h[];
ll dp[][][][][][][];
ll dfs(ll len,ll lim1,ll lim2,ll ok1,ll ok2,ll za,ll zb){
ll &ret=dp[len][lim1][lim2][ok1+][ok2+][za][zb];
if(ret!=-)return ret;
if(len==){
ret=za&&zb&&(ok1>||ok2<);
return ret;
}
ret=; --len;
int up1=lim1?:f[len];
int up2=lim2?:g[len];
for(int x=;x<=up1;x++)for(int y=;y<=up2;y++)
ret+=dfs(len,lim1|(x<f[len]),lim2|(y<g[len]),ok1==?(x&y)-h[len]:ok1,ok2==?(x^y)-h[len]:ok2,za|x,zb|y);
return ret;
}
int main(){
scanf("%d",&t);
while(t--){
memset(dp,-,sizeof(dp));
scanf("%lld%lld%lld",&A,&B,&C);
for(int i=;i<;i++){
f[i]=A%,A/=;
g[i]=B%,B/=;
h[i]=C%,C/=;
}
printf("%lld\n",dfs(,,,,,,));
}
return ;
}
另一个大佬的,我又复制了
结合大佬的
我自己水了一遍,嘻嘻
/* and 0&0=0; 0&1=0; 1&0=0; 1&1=1;
xor 0 ^ 0=0; 0 ^ 1=1; 1^ 0=1; 1^1=0;
3 4 2
5 2
8 5
7
1<=x<=a
1<=y<=b
条件 x&y>c x^y<c 分析得 只满足x^y<c 即可。
a,b,c<1e9 转换为二进制数位是30个。
*/ #include<bits/stdc++.h>
using namespace std;
typedef long long LL; LL dp[][][][][], a[],b[],c[]; LL dfs(LL len, LL And, LL Xor, LL limit1, LL limit2){
if(len==-)
{
if(And == || Xor == ) return 1ll;
return ;
}
//满足条件,直接返回最底层答案。
if(dp[len][And][Xor][limit1][limit2] != -)
return dp[len][And][Xor][limit1][limit2];
//没到达上界并且数位已经统计过,直接返回数量。 LL up1 = limit1 ? a[len] : ;
LL up2 = limit2 ? b[len] : ;
LL cnt =;
for(LL i = ; i <= up1; i++) {
for(LL j = ; j <= up2; j++) {
LL x = i & j, y = i ^ j;
LL _and = And;
LL _xor = Xor;
if(And == ) {
if(x > c[len]) _and = ;
else if(x < c[len]) _and = ;
}
if(Xor == ) {
if(y > c[len]) _xor = ;
else if(y < c[len]) _xor = ;
}
cnt += dfs(len-,_and,_xor,(i == up1) && limit1,limit2 &&(j==up2));
}
}
dp[len][And][Xor][limit1][limit2]=cnt;
return cnt;
} LL solve(LL aa,LL bb,LL cc)
{
LL ans=min(cc - , aa) + min (cc - , bb) + ;
for(LL i=;i<;i++){
a[i]=(aa & ); aa>>=;
b[i]=(bb & ); bb>>=;
c[i]=(cc & ); cc>>=;
//b[i]=bb%2,bb/=2;
//c[i]=cc%2,cc/=2;
}
return (dfs(,,,,)-ans);
} int main()
{
int t;
cin>>t;
while(t--)
{
memset(dp, -, sizeof(dp));
LL a,b,c;
cin>>a>>b>>c;
cout<<solve(a,b,c)<<endl;
}
return ;
}
2019 牛客网 第七场 H pair的更多相关文章
- 2019牛客多校第⑨场H Cutting Bamboos(主席树+二分)
原题:https://ac.nowcoder.com/acm/contest/889/H 题意: 给你一些竹子,q个询问,问你从第l到第r个竹子,如果你要用y次砍完它,并且每次砍下来的长度是相同的,问 ...
- 2019 牛客多校第二场 H Second Large Rectangle
题目链接:https://ac.nowcoder.com/acm/contest/882/H 题目大意 给定一个 n * m 的 01 矩阵,求其中第二大的子矩阵,子矩阵元素必须全部为 1.输出其大小 ...
- 2019牛客多校第二场H题(悬线法)
把以前的题补补,用悬线求面积第二大的子矩形.我们先求出最大子矩阵的面积,并记录其行三个方向上的悬线长度.然后排除这个矩形,记得还得特判少一行或者少一列的情况 #include <bits/std ...
- 2019牛客多校第一场H XOR 线性基模板
H XOR 题意 给出一组数,求所有满足异或和为0的子集的长度和 分析 n为1e5,所以枚举子集肯定是不可行的,这种时候我们通常要转化成求每一个数的贡献,对于一组数异或和为0.我们考虑使用线性基,对这 ...
- 2019牛客多校第二场 A Eddy Walker(概率推公式)
2019牛客多校第二场 A Eddy Walker(概率推公式) 传送门:https://ac.nowcoder.com/acm/contest/882/A 题意: 给你一个长度为n的环,标号从0~n ...
- 2019牛客多校第一场 I Points Division(动态规划+线段树)
2019牛客多校第一场 I Points Division(动态规划+线段树) 传送门:https://ac.nowcoder.com/acm/contest/881/I 题意: 给你n个点,每个点有 ...
- 2019牛客网暑假多校训练第四场 K —number
链接:https://ac.nowcoder.com/acm/contest/884/K来源:牛客网 题目描述 300iq loves numbers who are multiple of 300. ...
- 牛客网第9场多校E(思维求期望)
链接:https://www.nowcoder.com/acm/contest/147/E 来源:牛客网 题目描述 Niuniu likes to play OSU! We simplify the ...
- 牛客网第4场A
链接:https://www.nowcoder.com/acm/contest/142/A 来源:牛客网 题目描述 A ternary , , or . Chiaki has a ternary in ...
随机推荐
- 阿里云和微软共同开源的 OAM 对 Kubernetes 开发人员意味着什么?
上周,微软和阿里巴巴共同推出了开放应用模型(OAM),用于定义部署在任何地方的应用模型的一种规范.Rudr是Microsoft基于Kubernetes环境的OAM标准实现. 我用了一个周末来了解OAM ...
- JVM垃圾收集策略与算法
垃圾收集策略与算法 程序计数器.虚拟机栈.本地方法栈随线程而生,也随线程而灭:栈帧随着方法的开始而入栈,随着方法的结束而出栈.这几个区域的内存分配和回收都具有确定性,在这几个区域内不需要过多考虑回收的 ...
- 务必收藏备用:.net core中通过Json或直接获取图形验证码(数字验证码、字母验证码、混合验证码),有源代码全实战demo(开源代码.net core3.0)
很多人写的博客大家看了会一知半解,不知道怎么用,应该引用什么类库或者代码不全,这样很多小白很是头疼,尤其是尝新技术更是如此.我们这边不止告诉你步骤,而且还提供开源demo.随着时间的推移,我们的dem ...
- 7、pytest -- 捕获标准输出和标准错误输出
目录 1. 标准输出/标准错误输出/标准输入的默认捕获行为 2. 修改和去使能捕获行为 2.1. 文件描述符级别的捕获行为(默认) 2.2. sys级别的捕获行为 2.3. 去使能捕获行为 3. 使用 ...
- 学习笔记32_EF查询优化
*如果有 var temp = from m in dbContext.Model1 where m.属性1 == value select m; foreach(var m1 in temp)//这 ...
- CSPS模拟 83
紧张起来,集训已过半! 稍微有点惆怅.. T1 什么玩意,神仙树形dp? 没思路,先去T2. (遇到难题就绕过去是真的爽啊) T2 $n^2$暴力很好打 组合数是不是有规律? 找一下规律,发现十分眼熟 ...
- Kettle(6.0) 参数方式连接数据库
数据库连接条件(视自己实际情况而定) 数据库: Oracle 主机名称(IP): localhost 或 127.0.0.1 数据库名称(SID):MYORCL 端口号: 1521 用户名: scot ...
- Java自动化测试框架-11 - TestNG之annotation与并发测试篇 (详细教程)
1.简介 TestNG中用到的annotation的快速预览及其属性. 2.TestNG基本注解(注释) 注解 描述 @BeforeSuite 注解的方法只运行一次,在当前suite所有测试执行之前执 ...
- Abp vNext 自定义 Ef Core 仓储引发异常
问题 在使用自定义 Ef Core 仓储和 ABP vNext 注入的默认仓储时,通过两个 Repository 进行 Join 操作,提示 Cannot use multiple DbContext ...
- PHP实现开发者模式出现该公众号提供的服务出现故障 请稍后再试解决方法
PHP实现开发者模式出现该公众号提供的服务出现故障 请稍后再试解决方法 仔细检查下有没有echo等输出的代码 echo没有输出东西 就是报这个信息 所以调试信息都必须写入日记