Comet OJ - Contest #12


B
整个表格其实是一些联通块,取反操作不能跨连通块。所以直接统计一下每个连通块内数字不对的个数是不是偶数即可
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define gt(x,y) ((x)*m+y)
using namespace std;
const int M = 1100000;
int n,m,k,a[M],b[M],d[M],T,r,c,cnt=0,s[M];
char C[M];
bool check(int x,int y)
{
if(x<0 || y<0 || x>=n || y>=m) return 0;
return 1;
}
void dfs(int x,int y)
{
if(!check(x,y)) return ;
if(d[gt(x,y)]) return ;
d[gt(x,y)]=cnt;
dfs(x-r,y); dfs(x+r,y); dfs(x,y-c); dfs(x,y+c);
}
int main()
{
scanf("%d",&T);
for(;T;T--)
{
scanf("%d%d%d%d",&n,&m,&r,&c);
int B=1; cnt=0;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++) if(!d[gt(i,j)])
{
cnt++; dfs(i,j);
}
for(int i=0;i<n;i++)
{
scanf("\n%s",C);
for(int j=0;j<m;j++) a[gt(i,j)]=C[j]-'0';
}
for(int i=0;i<n;i++)
{
scanf("\n%s",C);
for(int j=0;j<m;j++)
{
k=C[j]-'0';
if(k!=a[gt(i,j)]) s[d[gt(i,j)]]^=1;
}
}
for(int i=1;i<=cnt;i++) if(s[i]) B=0;
if(B) printf("Yes\n");
else printf("No\n");
for(int i=0;i<=n*m;i++) a[i]=b[i]=d[i]=s[i]=0;
}
}
C
直接建图跑最短路
注意注意注意 :如果在某一车站有两辆公交车同事进站,他们之间要连双向边!
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
#define gt(x,y) ((x)*m+y)
using namespace std;
const int M = 2100000;
int t,m,k,b[M],d[M],T,cnt=0,n1,n2,s,t1,t2,head[M],nex[M*3],edge[M*3],ver[M*3],S;
priority_queue<pair<int,int> >q;
struct vv
{
int a,b;
} v[M];
bool cmp(vv a,vv b){return a.a<b.a;}
void add(int x,int y,int z)
{
ver[++cnt]=y, nex[cnt]=head[x], head[x]=cnt; edge[cnt]=z;
}
void dj()
{
for(int i=0;i<=t;i++) d[i]=0x3f3f3f3f, b[i]=0;
while(q.size()) q.pop(); d[S]=0;
q.push(make_pair(0,S));
while(q.size())
{
while(q.size() &&(b[q.top().second])) q.pop();
if(!q.size()) break;
int x=q.top().second; q.pop(); b[x]=1;
for(int i=head[x];i;i=nex[i])
{
int t=ver[i];
if(d[x]+edge[i]<d[t])
{
d[t]=d[x]+edge[i];
q.push(make_pair(-d[t],t));
}
}
}
}
int main()
{
scanf("%d",&T);
for(;T;T--)
{
scanf("%d%d%d%d%d%d",&m,&n1,&n2,&s,&t1,&t2);
t=m*(n1+n2)+2; S=t-1; cnt=0;
for(int i=0;i<m;i++)
{
for(int j=0;j<n1+n2;j++) scanf("%d",&v[j].a), v[j].b=j;
sort(v,v+n1+n2,cmp);
for(int j=0;j<n1+n2-1;j++)
{
add(gt(v[j].b,i),gt(v[j+1].b,i),v[j+1].a-v[j].a);
if(v[j+1].a==v[j].a) add(gt(v[j+1].b,i),gt(v[j].b,i),v[j+1].a-v[j].a);
}
if(i)
{
for(int j=0;j<n1;j++) add(gt(j,i-1),gt(j,i),0);
for(int j=0;j<n2;j++) add(gt(n1+j,i),gt(n1+j,i-1),0);
}
if(i!=s-1) continue;
for(int j=0;j<n1+n2;j++) if(v[j].a>=t1 && v[j].a<=t2) add(S,gt(v[j].b,i),v[j].a-t1);
for(int j=0;j<n1+n2;j++) if(v[j].a>=t1 && v[j].a<=t2) add(gt(v[j].b,i),t,t2-v[j].a);
}
dj();
printf("%d\n",min(d[t],t2-t1));
for(int i=0;i<=cnt;i++) edge[i]=ver[i]=nex[i]=0;
for(int i=0;i<=t;i++) head[i]=0;
}
}
D
异或和为n说明这两个数只有在n为1的位上值不同
也就是说如果n有第i位为1,那么两个数有且仅有一个第i位为1; 否则两个数这一位的取值相同
然后两数之差又不能超过m,就可以求出最大的n的子集记为g(窝就是这里求错了超时了15s来着 
然后就可以数位dp辣!
$f[i][A][B][G]$表示二进制下的第i位,x是不是a的上限,y是不是b的上限,xy中的哪个或者都没有达到g的上限
由于没想到什么妙妙的转移方法,我选择手写转移
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define LL long long
using namespace std;
const int M = 100001;
int T;
LL n,m,k,f[2][2][2][4],a,b,w,g;
int main()
{
scanf("%d",&T);
for(;T;T--)
{
scanf("%lld%lld%lld%lld",&a,&b,&n,&m); g=0;
LL e=0,S=0;
for(int i=60;i>=0;i--) if((1ll<<i)&n)
{
S+=(1ll<<i);
if(e+(1ll<<i)-(n-S)<=m) g+=(1ll<<i), e+=(1ll<<i);
else e-=(1ll<<i);
}
if(n-g>g || e<0)
{
printf("0\n");
continue;
}
for(int i=60;i>=0;i--) if(g&(1ll<<i))
{
w=(1ll<<i);
break;
}
memset(f,0,sizeof(f));
f[1][1][1][0]=1ll;
for(int i=60;i>=0;i--)
{
int t=i&1;
memset(f[t],0,sizeof(f[t]));
LL r=1ll<<i;
for(int A=0;A<=1;A++)
for(int B=0;B<=1;B++)
for(int k=0;k<=2;k++) if(f[!t][A][B][k])
{
if(n&r)
{
if(w==r)
{
int A1=0,B1=0,k1=0;
if((A && (a&r))||(!A))
{
int B1=0;
if(B && (b&r)==0) B1=1;
f[t][A][B1][1]=f[t][A][B1][1]+f[!t][A][B][k];
}
if((B && (b&r))||(!B))
{
int A1=0;
if(A && (a&r)==0) A1=1;
f[t][A1][B][2]=f[t][A1][B][2]+f[!t][A][B][k];
}
}
else
{
if(((k==1 && (g&r))||k!=1) &&( (A &&(a&r))|| !A))
{
int k1=0;
if(k==2 && ((g&r)==0)) k1=2;
if(k==1 && (g&r)) k1=1;
int B1=0;
if(B && (b&r)==0) B1=1;
f[t][A][B1][k1]=f[t][A][B1][k1]+f[!t][A][B][k];
}
if(((k==2 && (g&r))||k!=2) &&( (B &&(b&r))|| !B))
{
int k1=0;
if(k==1 && ((g&r)==0)) k1=1;
if(k==2 && (g&r)) k1=2;
int A1=0;
if(A && (a&r)==0) A1=1;
f[t][A1][B][k1]=f[t][A1][B][k1]+f[!t][A][B][k];
}
}
}
else
{
int A1=0, B1=0;
if(A && (a&r)==0) A1=1;
if(B && (b&r)==0) B1=1;
f[t][A1][B1][k]=f[t][A1][B1][k]+f[!t][A][B][k];
if((A && (a&r)==0) ||(B && (b&r)==0)) continue;
A1=0, B1=0;
if(A && (a&r)) A1=1;
if(B && (b&r)) B1=1;
f[t][A1][B1][k]=f[t][A1][B1][k]+f[!t][A][B][k];
}
}
}
LL res=0;
for(int i=0;i<=1;i++)
for(int j=0;j<=1;j++)
for(int k=0;k<=2;k++) res=res+f[0][i][j][k];
printf("%lld\n",res);
}
}
Comet OJ - Contest #12的更多相关文章
- Comet OJ - Contest #12 D
题目描述 求(x,y)的对数满足x∈[0,a],y∈[0,b],x⊕y=0且|x-y|<=m 题解 一种比较sb的做法是考虑x-y的借位,根据借位以及差值进行转移 还有一种比较正常的做法,假设一 ...
- Comet OJ - Contest #2 简要题解
Comet OJ - Contest #2 简要题解 cometoj A 模拟,复杂度是对数级的. code B 易知\(p\in[l,r]\),且最终的利润关于\(p\)的表达式为\(\frac{( ...
- Comet OJ - Contest #2简要题解
Comet OJ - Contest #2简要题解 前言: 我没有小裙子,我太菜了. A 因自过去而至的残响起舞 https://www.cometoj.com/contest/37/problem/ ...
- Comet OJ - Contest #4--前缀和
原题:Comet OJ - Contest #4-B https://www.cometoj.com/contest/39/problem/B?problem_id=1577传送门 一开始就想着暴力打 ...
- Comet OJ - Contest #11 题解&赛后总结
Solution of Comet OJ - Contest #11 A.eon -Problem designed by Starria- 在模 10 意义下,答案变为最大数的最低位(即原数数位的最 ...
- Comet OJ - Contest #8
Comet OJ - Contest #8 传送门 A.杀手皇后 签到. Code #include <bits/stdc++.h> using namespace std; typede ...
- Comet OJ - Contest #13-C2
Comet OJ - Contest #13-C2 C2-佛御石之钵 -不碎的意志-」(困难版) 又是一道并查集.最近做过的并查集的题貌似蛮多的. 思路 首先考虑,每次处理矩形只考虑从0变成1的点.这 ...
- Comet OJ - Contest #13 「火鼠的皮衣 -不焦躁的内心-」
来源:Comet OJ - Contest #13 芝士相关: 复平面在信息学奥赛中的应用[雾 其实是道 sb 题??? 发现原式貌似十分可二项式定理,然后发现确实如此 我们把 \(a^i\) 替换成 ...
- Comet OJ - Contest #13 「佛御石之钵 -不碎的意志-」(hard)
来源:Comet OJ - Contest #13 一眼并查集,然后发现这题 tmd 要卡常数的说卧槽... 发现这里又要用并查集跳过访问点,又要用并查集维护联通块,于是开俩并查集分别维护就好了 一开 ...
随机推荐
- cronsun任务管理器部署文档
一.cronsun介绍 1)cronsun产生的背景 大量的 crontab 任务散布在各台服务器,带来了很高的维护成本 任务没有按时执行,甚至失败了很久才发现,需要重试或排查 crontab 分散在 ...
- 在pythonanywhere部署你的第一个应用
pythonanywhere是一个免费的托管python的代码,可以测试你的web应用,用起来还是比较方便的,现在就来介绍如何在pythonanywhere部署你的应用. 下载你的代码 我的代码是托管 ...
- Android 线程池概念及使用
一:使用线程池的原因 在android开发中经常会使用多线程异步来处理相关任务,而如果用传统的newThread来创建一个子线程进行处理,会造成一些严重的问题: 在任务众多的情况下,系统要为每一个任务 ...
- Linux修改密码指令
1.在选择系统菜单界面,按 "e" 进入编辑模式 2.在以字符串“Linux16”开头的行,将光标移动到该行的结尾,然后输入“init=/bin/bash”,按 "Ctr ...
- 【Leetcode周赛】从contest-111开始。(一般是10个contest写一篇文章)
Contest 111 (题号941-944)(2019年1月19日,补充题解,主要是943题) 链接:https://leetcode.com/contest/weekly-contest-111 ...
- chrome插件研发手册
chrome插件研发手册 一:需求前景 对于研发的小伙伴来说,总会遇到这样的需求,想要通过代码操作已有网站的行为动作,如:自动填充表格内容(表单内容太多,想一键将表单内容填充):自动登录网站(网站登录 ...
- C#高级编程笔记(11至16章)异步/托管/反射/异常
11.1.2LINQ语句 LINQ查询表达式以from子句开始,以select或者group子句结束.在这两个子句之间可以跟零个或者多个from.let.where.join或者orderby子句. ...
- ps示例
博客PS示例 一显示指定真正用户名(RUID)或用户ID的进程 打开另外一个终端 [root@centos72 ~]# id wang uid=1000(wang) gid=1000(wang) gr ...
- Shiro安全框架的说明及配置入门
Shiro是什么? Shiro是一个非常强大的,易于使用的,开源的,权限框架.它包括了权限校验,权限授予,会话管理,安全加密等组件 什么时候使用它呢? 如果你是设计RBAC基础系统,需要编写大量用于权 ...
- JS中数据结构之二叉查找树
树是一种非线性的数据结构,以分层的方式存储数据.在二叉树上进行查找非常快,为二叉树添加或删除元素也非常快. 一棵树最上面的节点称为根节点,如果一个节点下面连接多个节点,那么该节点称为父节点,它下面的节 ...