NOIP2023 国庆集训 A 组 Day7
A. 字母还原(restore)
由加密方式一易得原串,剩下枚举情况判断即可,100pts;
本人代码较啰嗦……
#include
using namespace std;
int n,k;
struct note {
string s;
};
note c[4],c1[4];
bool f;
string work(string x,bool f,int p) {
char now[100002];
if(f)
for(int i=0; i'z')
now[i]=xx-'z'-1+'a';
else
now[i]=xx;
} else
for(int i=0; in;
for(int i=1; i>c[i].s;
for(int j=1; j<=3; j++)
c1[j]=c[j];
reverse(c1[1].s.begin(),c1[1].s.end());
for(int k=0; k<=6; k++) {
c1[2]=c[2];
c1[3]=c[3];
c1[2].s=work(c1[2].s,0,k);
c1[3].s=work(c1[3].s,1,k);
if(c1[2].s==c1[1].s && c1[3].s==c1[1].s) {
cout<<c1[1].s;
return 0;
}
}
for(int k=0; k<=6; k++) {
c1[2]=c[2];
c1[3]=c[3];
c1[2].s=work(c1[2].s,1,k);
c1[3].s=work(c1[3].s,0,k);
if(c1[2].s==c1[1].s && c1[3].s==c1[1].s) {
cout<<c1[1].s;
return 0;
}
}//first
for(int j=1; j<=3; j++)
c1[j]=c[j];
reverse(c1[2].s.begin(),c1[2].s.end());
for(int k=0; k<=6; k++) {
c1[1]=c[1];
c1[3]=c[3];
c1[1].s=work(c1[1].s,0,k);
c1[3].s=work(c1[3].s,1,k);
if(c1[1].s==c1[2].s && c1[3].s==c1[2].s) {
cout<<c1[2].s;
return 0;
}
}
for(int k=0; k<=6; k++) {
c1[1]=c[1];
c1[3]=c[3];
c1[1].s=work(c1[1].s,1,k);
c1[3].s=work(c1[3].s,0,k);
if(c1[1].s==c1[2].s && c1[3].s==c1[2].s) {
cout<<c1[2].s;
return 0;
}
}//second
for(int j=1; j<=3; j++)
c1[j]=c[j];
reverse(c1[3].s.begin(),c1[3].s.end());
for(int k=0; k<=6; k++) {
c1[2]=c[2];
c1[1]=c[1];
c1[2].s=work(c1[2].s,0,k);
c1[1].s=work(c1[1].s,1,k);
if(c1[2].s==c1[3].s && c1[3].s==c1[1].s) {
cout<<c1[3].s;
return 0;
}
}
for(int k=0; k<=6; k++) {
c1[2]=c[2];
c1[1]=c[1];
c1[2].s=work(c1[2].s,1,k);
c1[1].s=work(c1[1].s,0,k);
if(c1[2].s==c1[3].s && c1[3].s==c1[1].s) {
cout<<c1[3].s;
return 0;
}
}//third
return 0;
}
B. 棋盘染色(board)
比赛暴力模拟30pts;
由于新染的颜色会覆盖旧的颜色,所以我们需要考虑新染的位置有多少个被原先染过,且还要在相应位置更新标记数组,这显然是不好做的;所以我们考虑倒着染色,这样我们每次染色就无法覆盖旧的颜色了;对于每一列或者每一行,我们只要记录该行是否染过,以及有多少列与多少行被染过,就可以计算出答案了。 |
#include
using namespace std;
const int inf=10000001;
long long sum;
long long n,m,q,sl,sr;
int l[inf],r[inf],x[inf],y[inf],z[inf];
int main() {
freopen("board.in", "r", stdin);
freopen("board.out", "w", stdout);
scanf("%d%d%d",&n,&m,&q);
for(int i=1; i=1; i--) {
if(!x[i]) {
if(l[y[i]])
continue;
if(z[i])
sum+=m-sr;
sl++;
l[y[i]]=1;
} else {
if(r[y[i]])
continue;
if(z[i])
sum+=n-sl;
sr++;
r[y[i]]=1;
}
}
printf("%lld",sum);
return 0;
}
C. 为你写串(string)
易得一个a到达末尾的步数为该字符到末尾之间b的个数;可以发现每个a在操作过程中相对位置不会改变,所以必须等后一个a到达末端,该a才能到最后;那么每个a到达末尾的步数事实上已经固定了,为了方便,我们倒序将a移动至末尾,并记录移动后b的数量即可。 |
O(n) 直接扫一遍,100pts。
#include
using namespace std;
const long long M=1000000007;
string s;
long long ans,now;
int n;
int main() {
freopen("string.in", "r", stdin);
freopen("string.out", "w", stdout);
cin>>s;
n=s.size();
for(int i=n-1; i>=0; i--) {
if(s[i]=='b') {
now++;
now%=M;
} else {
ans+=now;
ans%=M;
now*=2;
now%=M;
}
}
cout<<ans;
return 0;
}
Miku!
原来你也知道miku!
骑士永在公主身旁(