【簡要題解】Educational Codeforces Round 123 簡要題解
老年選手打着玩。
Doors and Keys
有一個長度爲6的串,由
rgbRGB
各出現一次組成。小寫代表鑰匙,大寫代表門,問你是否可以走到6
直接模擬就好,然而我tmd看錯題了寫了個搜索還在想現在CF educational round的第一題怎麼這麼難了。
#include<bits/stdc++.h>
using namespace std;
int qr(){
int ret=0,c=getchar(),f=0;
while(!isdigit(c)) f=c==45,c=getchar();
while( isdigit(c)) ret=ret*10+c-48,c=getchar();
return f?-ret:ret;
}
char s[15];
int flg;
void dfs(int l,int r,int dep,int R,int G,int B){
//fprintf(stderr,"%d %d %d %d %d %d\n",l,r,dep,R,G,B);
if(R<0||G<0||B<0) return;
if(l==1&&r==6) return flg=1,void();
if(dep>15||flg) return;
while(islower(s[r+1])){
R+=s[r+1]=='r';
G+=s[r+1]=='g';
B+=s[r+1]=='b';
++r;
}
while(islower(s[l-1])){
R+=s[l-1]=='r';
G+=s[l-1]=='g';
B+=s[l-1]=='b';
--l;
}
if(isupper(s[l-1])) dfs(l-1,r,dep+1,R-(s[l-1]=='R'),G-(s[l-1]=='G'),B-(s[l-1]=='B'));
if(isupper(s[r+1])) dfs(l,r+1,dep+1,R-(s[r+1]=='R'),G-(s[r+1]=='G'),B-(s[r+1]=='B'));
}
int main(){
int T=qr();
while(T--){
flg=0;
scanf("%s",s+1);
for(int t=1;t<=1;++t)
if(islower(s[t]))
dfs(t,t,0,s[t]=='r',s[t]=='g',s[t]=='b');
if(flg) puts("YES");
else puts("NO");
}
return 0;
}
Anti-Fibonacci Permutation
一個排列是反斐波那契的,當且僅當\(\forall i \ge 3,p_{i-1}+p_{i-2}\not = p_i\),對於一個\(n\),請你輸出\(n\)個反斐波那契排列
排列小於\(10\)先搜索一下然後打表。
排列大於\(10\)考慮把\(1\quad 2\quad 3\)換成\(3\quad 1 \quad 2\),然後對於排列最後\(5\)個數進行next_permutation
,一定可以搞出很多出來,選出其中\(n\)個即可,複雜度\(O(5!n)\)
#include<bits/stdc++.h>
using namespace std;
int qr(){
int ret=0,c=getchar(),f=0;
while(!isdigit(c)) f=c==45,c=getchar();
while( isdigit(c)) ret=ret*10+c-48,c=getchar();
return f?-ret:ret;
}
const int maxn=150;
int a[maxn];
string ans[]={"","","","1 3 2 \n2 3 1 \n3 1 2 \n","1 2 4 3 \n1 3 2 4 \n1 4 2 3 \n1 4 3 2 \n","1 2 4 3 5 \n1 2 4 5 3 \n1 2 5 3 4 \n1 2 5 4 3 \n1 3 2 4 5 \n","1 2 4 3 5 6 \n1 2 4 3 6 5 \n1 2 4 5 3 6 \n1 2 4 5 6 3 \n1 2 5 3 4 6 \n1 2 5 3 6 4 \n","1 2 4 3 5 6 7 \n1 2 4 3 5 7 6 \n1 2 4 3 6 5 7 \n1 2 4 3 6 7 5 \n1 2 4 5 3 6 7 \n1 2 4 5 3 7 6 \n1 2 4 5 6 3 7 \n","1 2 4 3 5 6 7 8 \n1 2 4 3 5 6 8 7 \n1 2 4 3 5 7 6 8 \n1 2 4 3 5 7 8 6 \n1 2 4 3 6 5 7 8 \n1 2 4 3 6 5 8 7 \n1 2 4 3 6 7 5 8 \n1 2 4 3 6 7 8 5 \n","1 2 4 3 5 6 7 8 9 \n1 2 4 3 5 6 7 9 8 \n1 2 4 3 5 6 8 7 9 \n1 2 4 3 5 6 8 9 7 \n1 2 4 3 5 6 9 7 8 \n1 2 4 3 5 6 9 8 7 \n1 2 4 3 5 7 6 8 9 \n1 2 4 3 5 7 6 9 8 \n1 2 4 3 5 7 8 6 9 \n","1 2 4 3 5 6 7 8 9 10 \n1 2 4 3 5 6 7 8 10 9 \n1 2 4 3 5 6 7 9 8 10 \n1 2 4 3 5 6 7 9 10 8 \n1 2 4 3 5 6 7 10 8 9 \n1 2 4 3 5 6 7 10 9 8 \n1 2 4 3 5 6 8 7 9 10 \n1 2 4 3 5 6 8 7 10 9 \n1 2 4 3 5 6 8 9 7 10 \n1 2 4 3 5 6 8 9 10 7 \n"};
int main(){
int T=qr();
while(T--){
int n=qr();
if(n<=10) printf("%s",ans[n].c_str());
else{
for(int t=1;t<=n;++t) a[t]=t;
a[1]=3; a[2]=1; a[3]=2;
int cnt=0;
do{
int flg=1;
for(int t=3;t<=n;++t)
if(a[t-2]+a[t-1]==a[t])
flg=0,t=n;
if(flg){
++cnt;
for(int t=1;t<=n;++t)
printf("%d ",a[t]);
putchar('\n');
}
}while(next_permutation(a+n-5+1,a+n+1)&&cnt<n);
if(cnt!=n){
//cerr<<"qwq";
return 0;
}
}
}
return 0;
}
Increase Subarray Sums
給定一個序列和一個數\(x\),設\(f(k)\)表示選取序列中\(k\)個數加上\(x\)然後求出的最大子段和。輸出\(f(0)\dots f(n)\)
設\(Max[i]\)表示長度爲\(i\)的子段中的最大子段和,然後\(f(k)=\max(Max[i]+\min(i,k)\times x)\),複雜度\(O(n^2)\)
#include<bits/stdc++.h>
using namespace std;
int qr(){
int ret=0,c=getchar(),f=0;
while(!isdigit(c)) f=c==45,c=getchar();
while( isdigit(c)) ret=ret*10+c-48,c=getchar();
return f?-ret:ret;
}
typedef long long ll;
const int maxn=5005;
int a[maxn];
ll Max[maxn];
int main(){
int T=qr();
while(T--){
ll n=qr(),x=qr();
for(int t=1;t<=n;++t) a[t]=qr();
for(int t=1;t<=n;++t) Max[t]=-1e12;
for(int t=1;t<=n;++t){
int s=0;
for(int i=t;i<=n;++i){
s+=a[i];
Max[i-t+1]=max<ll>(Max[i-t+1],s);
}
}
for(int k=0;k<=n;++k){
ll ans=0;
for(int i=0;i<=n;++i)
ans=max<ll>(ans,min(k,i)*x+Max[i]);
printf("%lld ",ans);
}
putchar('\n');
}
return 0;
}
Cross Coloring
有一個\(n\times m\)的格子圖,初始是白色。你要進行\(q\)次操作,每次操作你要選擇\(k\)種(k種都不是白色)顏色中一個顏色,然後\(x_i\)行和\(y_i\)列就被染上這個顏色。問染色方案數。
答案\(=\)(在最終染色方案中有用的染色操作)\(^k\)。
考慮一個操作\(i\)是沒用的(即被其他染色操作完全覆蓋了),當且僅當
-
對於某個行,\(j>i,x_j=x_i\) 或者 在之後所有列都被染過一次顏色。
-
對於某個列,\(j>i,y_j=y_i\) 或者 在之後所有行都被染過一次顏色了。
複雜度\(O(n)\)
#include<bits/stdc++.h>
using namespace std;
int qr(){
int ret=0,c=getchar(),f=0;
while(!isdigit(c)) f=c==45,c=getchar();
while( isdigit(c)) ret=ret*10+c-48,c=getchar();
return f?-ret:ret;
}
const int maxn=2e5+5;
const int mod=998244353;
typedef long long ll;
int ksm(const int&ba,const int&p){
int ret=1;
for(int t=p,b=ba;t;t>>=1,b=1ll*b*b%mod)
if(t&1) ret=1ll*ret*b%mod;
return ret;
}
int row[maxn],col[maxn];
pair<int,int> que[maxn];
int main(){
int T=qr();
while(T--){
int n=qr(),m=qr(),k=qr(),Q=qr(),fcnt=Q,cntr=0,cntc=0;
for(int t=1;t<=n;++t) row[t]=0;
for(int t=1;t<=m;++t) col[t]=0;
for(int t=1;t<=Q;++t) que[t].first=qr(),que[t].second=qr();
for(int t=Q;t;--t){
int cnt=0;
if(row[que[t].first]||cntc==m) ++cnt;
if(!row[que[t].first]) row[que[t].first]=t,++cntr;
if(col[que[t].second]||cntr==n) ++cnt;
if(!col[que[t].second]) col[que[t].second]=t,++cntc;
if(cnt==2) --fcnt;
}
int ans=ksm(k,fcnt);
printf("%d\n",ans);
}
return 0;
}
Expand the Path
有一個機器人,遵循
DR
規則,即遇到一個D
就往下走一格,遇到一個R
就往右走一格。現在初始給你一個DR
串,你每次可以選擇任何一個字母,比如D
,把他變成DD
。問你可以經過多少格?一個格子可以被經過,當且僅當存在一種操作該DR
串的方式,使得機器人在不走出地圖的情況下經過這個格子。
考慮那些走不到的格子,是原DR
串走出的輪廓線下方或者右方,模擬一下即可。(有事待會再詳細更博,未完待續)
#include<bits/stdc++.h>
using namespace std;
int qr(){
int ret=0,c=getchar(),f=0;
while(!isdigit(c)) f=c==45,c=getchar();
while( isdigit(c)) ret=ret*10+c-48,c=getchar();
return f?-ret:ret;
}
typedef long long ll;
const int maxn=2e5+5;
char s[maxn];
int main(){
int T=qr();
while(T--){
int n=qr();
scanf("%s",s+1);
int L=strlen(s+1);
int flg=1;
for(int t=2;t<=L;++t)
if(s[t]!=s[t-1])
flg=0;
if(flg){
printf("%d\n",n);
continue;
}
ll ans=1ll*n*n,sav=0,lastcnt=0;
for(int t=L;t;--t){
if(s[t]=='D') ++sav,lastcnt=0;
if(s[t]=='R') ans-=sav,++lastcnt;
}
if(s[1]=='R') ans-=(n-1-sav)*lastcnt;
sav=0;
for(int t=L;t;--t){
if(s[t]=='R') ++sav,lastcnt=0;
if(s[t]=='D') ans-=sav,++lastcnt;
}
if(s[1]=='D') ans-=(n-1-sav)*lastcnt;
printf("%lld\n",ans);
for(int t=1;t<=L;++t) s[t]=0;
}
return 0;
}