C - Round Corridor CodeForces - 1200C
类型:水题
wa因:
1.A wall always exists at the 12 o’clock position.题意是这么说的,我错误的理解为了是在12点的那个轴上,因为看图上是这样的,但是图上那是巧合刚好2个是偶数。
2.注意是longlong,这导致我wa在第4发。
正解思路:
1.相当于两个环,分成不同的量,一个环分成n份,另一个分成m个,每一个是
,另一个是
,
=
,故
=
。也就是求
的最简分数形式,即
。
在1环钟,为n/gcd 个数为1组,在2环钟,为m/gcd 个数字为1组,通过这个判断看他们分别在第几组,如果他们组号相同就是相通的。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll gcd(ll a,ll b)
{
while(a&&a&&(a>=b? a%=b:b%=a));
return a+b;
}
ll g1,g2;
ll deal(ll a,ll b)
{
return a==1?(b-1)/g1:(b-1)/g2;
}
int main(void)
{
ll n,m,q;
scanf("%lld %lld %lld",&n,&m,&q);
ll gcc;
gcc=gcd(n,m);
g1=n/gcc;
g2=m/gcc;
ll get=0;
ll ax,ay,bx,by;
while(q--)
{
scanf("%lld %lld %lld %lld",&ax,&ay,&bx,&by);
ll get1=deal(ax,ay);
ll get2=deal(bx,by);
get1==get2?printf("YES\n"): printf("NO\n");
}
return 0;
}
D题 思维前缀
参考错误原因:
情况:wa在第7发,思路错误
参考思路错误原因:
a.认为一定选择填的那个矩阵,左上角一定是B,但是也可能是W,比如
WBWW
BBWW
BBBB
BBBB
如果只能从B开始,那么最佳位置是从(2,1)开始,答案只能是2;
而若从W开始,那么从(1,1)开始,就能得到3.
b.就是计算贡献值的时候重合了,看第2个样例能不能过,就知道有没有犯这个错误了。
正解思路:
1.统计某一行(列)到第几个的时候有几个B,得到dp1[x][y],dp2[x][y];
2.统计不用修改,该行或列就是全W的,得到ans1;
3.统计在(x,y)处作为该行操作的起始点时,就能使该行都为W,得到
ok1[x][y]=1,ok2[x][y]=1,否则或者改行(列)本来就是满的,就是为0。
4.
由以上已经得到了一个nn的零一矩阵,1表示为行起点或列起点的时候就可以整行(列)为W。
方法一:枚举每个点作为左上角点,这个时候再用循环遍历k2遍。那么也就是n* k *2
方法二:第2个方法由重复,也就意味着可以再用前缀和的方法简化。
记录yes1[x][y]]为把第1行到第x行的第y列都作为行起始点,能够实现行都为W的行数。
如此打表出来后,再去计算,为n * n * 2.
#include<cstdio>
#include<algorithm>
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e3+10;
int dp1[maxn][maxn],dp2[maxn][maxn];//表示这个行(列)x中,从第1个到第y个有多少个B。
int ok1[maxn][maxn],ok2[maxn][maxn];//表示这个格作为行(列)的起始格,可以使该行(列)满W.
int yes1[maxn][maxn],yes2[maxn][maxn];
int n,k;
int get_ans1()
{
int ans1=0;
for(int i=1;i<=n;++i)ans1+=(dp1[i][n]==0);
for(int i=1;i<=n;++i)ans1+=(dp2[i][n]==0);
return ans1;
}
void make_ok()
{
int now;
for(int i=1;i<=n;++i)
for(int d=1;d<=n-k+1;++d)
{
if(dp1[i][n])
{
now=dp1[i][d-1]+dp1[i][n]-dp1[i][d+k-1];
if(now==0)ok1[i][d]=1;
}
if(dp2[i][n])
{
now=dp2[i][d-1]+dp2[i][n]-dp2[i][d+k-1];
if(now==0)ok2[i][d]=1;
}
}
}
void make_yes()
{
for(int i=1;i<=n;++i)
for(int d=1;d<=n;++d)
{
yes1[i][d]=yes1[i-1][d]+(ok1[i][d]==1);
yes2[i][d]=yes2[i-1][d]+(ok2[i][d]==1);
}
}
int main(void)
{
scanf("%d %d",&n,&k);
for(int i=1;i<=n;++i)
{
getchar();
for(int d=1;d<=n;++d)
{
char get=getchar();
dp1[i][d]=dp1[i][d-1]+(get=='B');
dp2[d][i]=dp2[d][i-1]+(get=='B');
}
}
int ans1=get_ans1();
make_ok();
make_yes();
int ans2=0;
for(int i=1;i<=n-k+1;++i)
for(int d=1;d<=n-k+1;++d)
{
ans2=max(ans2,yes1[i+k-1][d]-yes1[i-1][d]+yes2[d+k-1][i]-yes2[d-1][i]);
}
printf("%d\n",ans2+ans1);
return 0;
}
E - Compress Words CodeForces - 1200E
题解:kmp
#include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;
const int maxn=1e6+10;
char now[maxn],duan[maxn];
int f[maxn];
int cnt;
void mke_mpt()
{
int len=strlen(duan);
f[0]=f[1]=0;
for(int i=1;i<len;++i)
{
int j=f[i];
while(j&&duan[i]!=duan[j])j=f[j];
f[i+1]= duan[i]==duan[j]? j+1:0;
}
}
int pipei()
{
int len=strlen(duan);
int j=0;
int i=max(cnt+1-len,0);
for(;i<=cnt;++i)
{
while(j&&now[i]!=duan[j])j=f[j];
j= now[i]==duan[j]?j+1:0;
}
return j;
}
void add(int a)
{
int len=strlen(duan);
for(int i=a;i<len;++i){now[++cnt]=duan[i];}
}
int main(void)
{
int n;
scanf("%d",&n);
scanf("%s",now);
cnt=strlen(now)-1;
for(int i=2;i<=n;++i)
{
scanf("%s",duan);
mke_mpt();
int num=pipei();
add(num);
}
printf("%s",now);
return 0;
}