只要wolf的四邻接格子中没有sheep,则肯定有办法放狗使得狼无法接触到羊,把所有空格替换成狗就行了。
#include
using namespace std;
typedef long long ll;
const int maxn=505;
const int maxm=100005;
const int maxe=200005;
const int mod=1e9+7;
int n,m;
char ma[maxn][maxn];
int dx[4]={-1,0,0,1};
int dy[4]={0,-1,1,0};
int main(){
scanf("%d%d",&n,&m);
for(int i=0;iscanf("%s",ma[i]);
}
bool f=1;
for(int i=0;ifor(int j=0;jif(ma[i][j]=='W'){
for(int k=0;k<4;k++){
int nx=i+dx[k];
int ny=j+dy[k];
if(nx<0||nx>=n)continue;
if(ny<0||ny>=m)continue;
if(ma[nx][ny]=='S'){f=0;break;}
}
}
if(f==0)break;
}
if(f==0)break;
}
if(f==0){printf("No\n");return 0;}
printf("Yes\n");
for(int i=0;ifor(int j=0;jif(ma[i][j]=='.')ma[i][j]='D';
}
}
for(int i=0;iprintf("%s\n",ma[i]);
}
return 0;
}
首先处理处所有质数。
思路是先找出每个数作为X1的情况下,X0的最小值是多少,然后对于x2遍历它的每个素因子,确定x1的取值范围,然后就遍历那个取值范围找出答案最小值。
1.确定每个x1对应的x0最小值的方法就是:用每个质数去更新它的倍数a=k*prime(k>=2),x0[a]=min(x0[a],prime*(k-1)+1)
2.最终确定的x1的取值范围肯定是一段连续的区间(k to n),确定范围的方法类似(1)
#include
using namespace std;
typedef long long ll;
const int maxn=1000005;
const int maxm=100005;
const int maxe=200005;
const int mod=1e9+7;
int n,m;
int prime[maxn];
int tot;
bool vis[maxn];
void init(){
tot=0;
for(int i=2;iif(vis[i])continue;
prime[tot++]=i;
for(int j=2;j*i<=maxn;j++){
vis[j*i]=1;
}
}
}
int pre[maxn];
int main(){
init();
scanf("%d",&n);
memset(pre,0x3f,sizeof(pre));
for(int i=0;iint num=prime[i];
for(int j=2;j*num<=n;j++){
pre[j*num]=min(pre[j*num],(j-1)*num+1);
}
}
int ans=0x3f3f3f3f;
int cnt=n;
for(int i=tot-1;i>=0;i--){
if(prime[i]>=n)continue;
if(n%prime[i])continue;
int pos=((n/prime[i])-1)*prime[i]+1;
while(cnt>=pos){
ans=min(ans,pre[cnt]);
cnt--;
}
}
printf("%d\n",ans);
return 0;
}
考虑每天新增雪对后面每一天的融化数量的贡献,发现第i天的雪在第k天融化完,则它对第i到k-1天的贡献都是t[j],对第k天的贡献就是剩余的雪的数量。
所以二分雪到第几天刚好融化完,然后用类似前缀和的方式对区间打标记处理一下即可。
#include
using namespace std;
typedef long long ll;
const int maxn=101005;
const int maxm=100005;
const int maxe=200005;
const int mod=1e9+7;
int n,m;
ll v[maxn];
ll t[maxn];
ll sum[maxn];
ll a[maxn];
ll ans[maxn];
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%lld",&v[i]);
for(int i=1;i<=n;i++)scanf("%lld",&t[i]);
for(int i=1;i<=n;i++){
sum[i]=sum[i-1]+t[i];
}
for(int i=1;i<=n;i++){
int pos=lower_bound(sum+i,sum+n+1,v[i]+sum[i-1])-sum;
ans[pos]+=v[i]+sum[i-1]-sum[pos-1];
a[i]++;
a[pos]--;
}
for(int i=1;i<=n;i++){
a[i]+=a[i-1];
ans[i]+=a[i]*t[i];
}
for(int i=1;i<=n;i++){
printf("%lld ",ans[i]);
}
return 0;
}
暴力一点就是n方的,肯定超时的做法。
异或就可以按位考虑,每个数想要异或之后变得更小,肯定是异或一个二进制位最为相似且不同位尽量少且尽量在低位的,所以建棵字典树用来查询即可,把每个数字变成一个三十位的二进制字符串插入到trie上就行了,涉及到删除操作开一个计数数组即可。
#include
using namespace std;
typedef long long ll;
#define MP make_pair
const int maxn=300005;
const int maxm=(1<<25);
int n,m;
int a[maxn],p[maxn];
int ch[maxm][2];
int cou[maxm];
int sz;
void inser(int num){
int u=0;
for(int i=30;i>=0;i--){
int c=0;
if((1<1;
if(!ch[u][c]){
ch[sz][0]=ch[sz][1]=0;
cou[sz]=0;
ch[u][c]=sz++;
}
cou[u]++;
u=ch[u][c];
}
cou[u]++;
}
void build(){
for(int i=0;iint cal(int num){
int num1=num;
int u=0;
for(int i=30;i>=0;i--){
int c=0;
if((1<1;
if(!ch[u][c]||!cou[ch[u][c]]){
c=1-c;
}
num1^=(c<return num1;
}
int main(){
scanf("%d",&n);
for(int i=0;iscanf("%d",&a[i]);
for(int i=0;iscanf("%d",&p[i]);
sz=1;
memset(ch[0],0,sizeof(ch[0]));
build();
for(int i=0;iprintf("%d ",cal(a[i]));
}
return 0;
}
推一推几个式子就可以发现:
B可以变成C,所以两串中的C都当成B来看。
任何B之前可以添加任意数量的A,所以对于查询区间非末尾的A都可以无视掉。
B的数量自能增加不能减少,且只能偶数倍的增加
区间末尾的A只能直接减少三个或者一个A变成两个B或者两个A变成两个B。
所以统计一下B数量的前缀和和A的后缀长度,然后分类讨论一下就可以了。
#include
using namespace std;
typedef long long ll;
#define MP make_pair
const int maxn=100005;
const int maxm=(1<<25);
int n,m;
char s[maxn],t[maxn];
int bn1[maxn],bn2[maxn];
int an1[maxn],an2[maxn];
int a,b,c,d;
int main(){
scanf("%s%s",s+1,t+1);
n=strlen(s+1),m=strlen(t+1);
for(int i=1;i<=n;i++){
bn1[i]+=bn1[i-1]+(s[i]!='A'?1:0);
if(s[i]!='A')continue;
an1[i]=1+an1[i-1];
}
for(int i=1;i<=m;i++){
bn2[i]+=bn2[i-1]+(t[i]!='A'?1:0);
if(t[i]!='A')continue;
an2[i]=1+an2[i-1];
}
int Q;
scanf("%d",&Q);
while(Q--){
scanf("%d%d%d%d",&a,&b,&c,&d);
int b1num=bn1[b]-bn1[a-1];
int a1num=min(b-a+1,an1[b]);
int b2num=bn2[d]-bn2[c-1];
int a2num=min(d-c+1,an2[d]);
if(b1num>b2num){putchar('0');continue;}
if(b1num==b2num){
if(a1numputchar('0');continue;}
int cha=a1num-a2num;
if(cha%3){putchar('0');}
else putchar('1');
continue;
}
if(b1num==0){
if(b2num%2){putchar('0');continue;}
if(a1num<=a2num){putchar('0');continue;}
int lef=(a1num-a2num)%3;
if(lef>b2num){putchar('0');continue;}
putchar('1');
continue;
}
if(b1numint cha=b2num-b1num;
if(cha%2){putchar('0');continue;}
if(a1numputchar('0');continue;}
int lef=(a1num-a2num)%3;
if(b1num+lef>b2num){putchar('0');continue;}
putchar('1');
continue;
}
}
return 0;
}