2021牛客暑期多校训练营8
A Ares, Toilet Ares
阅读理解题,英语一定要好好学
D OR
重要结论,a+b=a|b+a&b
然后a+b和a|b的约数就可以转化到a&b和a|b的约数,然后按位考虑算出可能答案乘起来即可。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
#define N 101000
#define int long long
int dp[N][2],b[N],c[N],d[N],a[N];
signed main(){
int n;
scanf("%d",&n);
for(int i=2;i<=n;i++)scanf("%d",&b[i]);
for(int i=2;i<=n;i++)scanf("%d",&c[i]);
for(int i=2;i<=n;i++){
d[i]=c[i]-b[i];
a[i]|=d[i],a[i-1]|=d[i];
if(d[i]<0){
printf("0");
return 0;
}
}
int ans=0;
for(int i=0;i<=29;i++){
int bit=1ll<<i;
for(int j=n;j>=1;j--){
if(j==n){
int x=b[j]&bit;
if(x)dp[j][0]=dp[j][1]=1;
else dp[j][0]=1,dp[j][1]=0;
}
else if(j==1){
int y=b[j+1]&bit;
if(y){
dp[j][0]=dp[j+1][1],dp[j][1]=dp[j+1][0];
if((a[j]&bit)&&(a[j+1]&bit))dp[j][1]+=dp[j+1][1];
}
else if(!y)dp[j][0]=dp[j+1][0],dp[j][1]=0;
}
else{
int x=b[j]&bit;
int y=b[j+1]&bit;
if(x&&y){
dp[j][1]=dp[j+1][0],dp[j][0]=dp[j+1][1];
if((a[j]&bit)&&(a[j+1]&bit))dp[j][1]+=dp[j+1][1];
}
else if(x&&!y)dp[j][0]=dp[j+1][0],dp[j][1]=0;
else if(!x&&y)dp[j][0]=dp[j+1][1],dp[j][1]=0;
else if(!x&&!y)dp[j][0]=dp[j+1][0],dp[j][1]=0;
}
if(a[j]&bit)dp[j][0]=0;
}
if(i==0)ans=dp[1][0]+dp[1][1];
else ans=ans*(dp[1][0]+dp[1][1]);
}
printf("%lld",ans);
return 0;
}
E Rise of Shadows
找到是质数的润年,我还真写了。
F Robots
多次询问问一个只能向左,向右或者能向左向右的机器人能否从一个有障碍网格图的一个地方到另一个地方。
正解释整体二分,我当时写的网络流(T),最后我用bitset暴力通过了此题。
对于只能向左或向右的前缀和求答案。
对于能向左和向右的,bitset记录能到达的位置,暴力转移统计答案即可。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<bitset>
#include<queue>
using namespace std;
#define N 550
int n,m;
int sum[N][N],a[N][N],ans[501000];
char s[N];
bitset<N*N> bit[2][N];
int read(){
int sum=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){sum=sum*10+ch-'0';ch=getchar();}
return sum*f;
}
int id(int x,int y){
return (x-1)*m+y;
}
struct query{
int x,y,id,nxt;
}qu[501000];
int head[N][N],cnt;
void add(int x_1,int y_1,int x_2,int y_2,int id){
cnt++;
qu[cnt].nxt=head[x_1][y_1];
qu[cnt].x=x_2;
qu[cnt].y=y_2;
qu[cnt].id=id;
head[x_1][y_1]=cnt;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%s",s+1);
for(int j=1;j<=m;j++)a[i][j]=s[j]-'0',sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+a[i][j];
}
int q;
scanf("%d",&q);
for(int i=1;i<=q;i++){
int type,x_1,y_1,x_2,y_2;
scanf("%d%d%d%d%d",&type,&x_1,&y_1,&x_2,&y_2);
if(type==1){
if(y_2!=y_1)ans[i]=0;
else if(x_2<x_1)ans[i]=0;
else if(sum[x_2][y_2]-sum[x_1-1][y_2]-(sum[x_2][y_1-1]-sum[x_1-1][y_1-1])!=0)ans[i]=0;
else ans[i]=1;
}
else if(type==2){
if(x_2!=x_1)ans[i]=0;
else if(y_2<y_1)ans[i]=0;
else if(sum[x_2][y_2]-sum[x_1-1][y_2]-(sum[x_2][y_1-1]-sum[x_1-1][y_1-1])!=0)ans[i]=0;
else ans[i]=1;
}
else add(x_1,y_1,x_2,y_2,i);
}
for(int i=n;i>=1;i--)
for(int j=m;j>=1;j--){
if(a[i][j]==1){
bit[i%2][j].reset();
continue;
}
else {
bit[i%2][j]=(bit[(i+1)%2][j]|bit[i%2][j+1]);
bit[i%2][j][id(i,j)]=1;
}
for(int k=head[i][j];k;k=qu[k].nxt){
int x=qu[k].x,y=qu[k].y;
ans[qu[k].id]=bit[i%2][j][id(x,y)];
}
}
for(int i=1;i<=q;i++)
if(ans[i]==1)printf("yes\n");
else printf("no\n");
return 0;
}
K Yet Another Problem About Pi
显然开始位置在一个交叉点,一个结论是只能走对角和短边。
不知道为什么,挖个坑。