题解-比赛CF1332
[A]Exercising Walk
\(T\) 组测试数据,每次给定 \(a,b,c,d,x,y,x_1,y_1,x_2,y_2\)。起点是 \((x,y)\),要左走 \(a\) 步,右走 \(b\) 步,下走 \(c\) 步,上走 \(d\) 步(这题的 \(x\) 和 \(y\) 轴与平时相反)。求是否有走法,使得走的过程总是满足 \(x_1\le x\le x_2\),\(y_1\le y\le y_2\)。如果满足输出 \(\texttt{YES}\),否则输出 \(\texttt{NO}\)。
数据范围:\(1\le T\le 10^3\),\(0\le a,b,c,d\le 10^8\),\(a+b+c+d\ge 1\),\(-10^8\le x_1\le x\le x_2\le 10^8\),\(-10^8\le y_1\le y\le y_2\le 10^8\)。
本来以为直接找到最终点看看在不在范围内就够了,但是后来发现过不了样例。
有一种特殊情况:\([x_1=x]\&[x=x_2]\&[a,b>0]\&[a+b=0]\)(一走就走出范围了),答案是 \(\texttt{NO}\),你会输出 \(\texttt{YES}\)。
对于 \(y,c,d\) 同理,所以特判一下就过了。
易错点:
- 没看清这题的 \(x\) 和 \(y\) 轴与平时相反这个特点。
- 没考虑到特殊情况(你样例都过不了啊)。
代码:
//Data
int a,b,c,d,x,y,x1,y1,x2,y2;
il int yes(){
if(a&&b) if(x==x1&&x==x2) return 0;
if(c&&d) if(y==y1&&y==y2) return 0;
x-=a,x+=b,y-=c,y+=d;
return x1<=x&&x<=x2&&y1<=y&&y<=y2;
}
//Main
int main(){
re int t;
scanf("%d",&t);
while(t--){
scanf("%d%d%d%d%d%d%d%d%d%d",&a,&b,&c,&d,&x,&y,&x1,&y1,&x2,&y2);
if(yes()) puts("YES"); else puts("NO");
}
return 0;
}
[B]Composite Coloring
\(T\) 组测试数据,每次给定一个长度为 \(n\) 的合数序列 \(a_i\),需要将每个数染上颜色,使满足对于任意两个颜色相同的数不互质。求一种颜色数为 \(m\) 的染色方案(\(m\) 自选,不需最小,只需满足 \(m\in[1,11]\))。
数据范围:\(1\le T\le 10^3\),\(1\le n\le 10^3\),\(4\le a_i\le 10^3\),\(1\le \sum n\le 10^4\)。
对于任意满足数据范围限制的序列绝对有解。
对于任何合数 \(a_i\le 1000\),必然有 \(d\) 满足 \([d|i]\&[d<32]\)。
\([1,32]\) 中正好有 \(11\) 个质数,所以遍历每个质数然后把它们的倍数染同色即可。
易错点:
题目中有说对于 \(1\sim m\) 中的每个颜色,必须有该颜色的数,所以需要对颜色离散化。
代码:
//Data
const int N=1000;
int n,a[N+7],co[N+7];
//Prime
bitset<37> np;
vector<int> p;
//Main
int main(){
for(re int i=2;i<=32;i++){
if(!np[i]) p.pb(i);
for(re int j:p)if(i*j>N) break;else np[i*j]=1;
}
re int t;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(re int i=1;i<=n;i++)
scanf("%d",a+i);
re int C=0;
fill(co+1,co+n+1,0);
for(re int j:p){
re int ttt=0;
for(re int i=1;i<=n;i++){
if(!co[i]&&a[i]%j==0){ttt=1,co[i]=C+1;}
}
if(ttt) C++;
}
printf("%d\n",C);
for(re int i=1;i<=n;i++)
printf("%d%c",co[i],"\n "[i<n]);
}
return 0;
}
[C]K-Complete Word
\(T\) 组测试数据,给定 \(n\) 和 \(k\) 满足 \(k|n\),给定一个长度为 \(n\) 的字符串 \(s\),求最少修改 \(s\) 的几个字母,使得 \(s\) 是回文串并且对于所有 \(1\le i\le n-k\),满足 \(s_i=s_{i+k}\)。
数据范围:\(1\le t\le 10^5\),\(1\le k<n\le 2\times 10^5\),\(\sum n\le 2\times 10^5\)。
第二个条件等价于 \(s\) 的 \(\frac nk\) 个 \(k\) 长子段相等;因为 \(s\) 是回文的,所以每个 \(k\) 长子段也是回文的。
所以对于每个 \(1\le i\le \lfloor\frac k2\rfloor\),满足:
如果 \(k\in \mathbb{odd}\),对于 \(i=\frac {k+1}2\) 满足:
所以把每群相等的字符中出现次数最多的字符留着,把别的字符改成该字符即可。
代码:
//Data
const int N=200000;
int n,k;
char s[N+7];
int cnt[30];
//Main
int main(){
re int t;
scanf("%d",&t);
while(t--){
scanf("%d%d\n%s",&n,&k,s+1);
re int ans=0;
for(re int i=1;i<=k/2;i++){
memset(cnt,0,sizeof cnt);
re int tmp=0;
for(re int j=i;j<=n;j+=k) cnt[s[j]-'a']++,tmp++;
for(re int j=k+1-i;j<=n;j+=k) cnt[s[j]-'a']++,tmp++;
re int mx=0;
for(re int i=1;i<26;i++) if(cnt[i]>cnt[mx]) mx=i;
ans+=tmp-cnt[mx];
}
if(k&1){ //k∈odd
int i=(k+1)/2;
memset(cnt,0,sizeof cnt);
re int tmp=0;
for(re int j=i;j<=n;j+=k) cnt[s[j]-'a']++,tmp++;
re int mx=0;
for(re int i=1;i<26;i++) if(cnt[i]>cnt[mx]) mx=i;
ans+=tmp-cnt[mx];
}
printf("%d\n",ans);
}
return 0;
}