Codeforces Round 981 (Div3,A-F)

A - Sakurako and Kosuke

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void solve(){
int n;cin>>n;
int m=1,cnt=0;
for(int i=1;;i++){
if(i&1){
cnt-=(2*i-1);
}else{
cnt+=(2*i-1);
}
if(abs(cnt)<=n){
continue;
}else{
m=i;
break;
}
}
cout<<(m&1?"Kosuke":"Sakurako")<<"\n";
}

B - Sakurako and Water

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void solve(){
int n;cin>>n;
vector<vector<int>>g(n+1,vector<int>(n+1));
map<int,vector<int>>mp;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
cin>>g[i][j];
if(g[i][j]<0){
mp[i-j].push_back(abs(g[i][j]));
}
}
}
int ans=0;
for(auto &[x,y]:mp){
sort(y.begin(),y.end(),greater<int>());
ans+=y[0];
}
cout<<ans<<"\n";
}

C - Sakurako’s Field Trip

C这个题有一点说法,其实想明白什么时候换就可以

从左到n/2的位置每次考虑是否交换当前位置,当i这个位置与i-1的数相同的时候或者n-i+1与其下一个数(就是当前数与其遍历过的上一个数)相同的时候选择交换,可以证明这样操作对答案的增益一定是非负的

证明如下

  1. 如果a[i]==a[n-i+1],操作无影响

  2. a[i]!=a[n-i+1],

    设交换之前点i对答案的增益为 ans=(a[i]==a[i-1]+a[i]==a[i+1]+a[n-i+1]==a[n-i]+a[n-i+1]==a[n-i+2])

    交换之后点i对答案的增益为 ans1=(a[n-i+1]==a[i-1]+a[n-i+1]==a[i+1]+a[i]==a[n-i]+a[i]==a[n-i+2])

    最坏情况就是

    a[i]==a[i-1]&&a[i]!=a[i+1]&&a[n-i+1]!=a[n-i]&&a[n-i+1]!=a[n-i+2]

    a[n-i+1]==a[i+1]&&a[i]==a[n-i]&&a[i]==a[n-i+2]

    这样的话,交换之后答案多2,但是这种情况下在下一次交换过程中会被重新满足条件执行交换

综上,一直执行交换,最后求答案即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void solve(){
int n;cin>>n;
vector<int>a(n+10,0),cnt(n+1,0);
for(int i=1;i<=n;i++) cin>>a[i];
int ans=0;
for(int i=1;i<=(n+1)/2;i++){
if(a[i]==a[i-1]||a[n-i+1]==a[n-i+2]){
swap(a[i],a[n-i+1]);
}
}
for(int i=1;i<=n-1;i++){
if(a[i]==a[i+1]) ans++;
}
cout<<ans<<"\n";
}

D - Kousuke’s Assignment

没啥说的,遇到0就断开一定是最优的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
void solve(){
int n;cin>>n;
vector<int>a(n+1),pre(n+1,0);
for(int i=1;i<=n;i++){
cin>>a[i];
pre[i]=pre[i-1]+a[i];
}
int ans=0,lst=0;
map<int,int>mp;
for(int i=1;i<=n;i++){
if(a[i]==0){
lst=i;ans++;
continue;
}
int d=pre[i]-pre[lst];
if(d==0){
if(lst<i){
ans++;
lst=max(i,lst);
}
}else if(mp.count(d)){
if(lst<mp[d]){
ans++;
lst=max(i,lst);
}
}
mp[d]=i;
}
cout<<ans<<'\n';
}

E - Sakurako, Kosuke, and the Permutation

每次交换完之后就保证当前位置不再交换,这样顺序从1到n就是最小交换次数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void solve(){
int n;cin>>n;
vector<int>a(n+1),pos(n+1);
for(int i=1;i<=n;i++){
cin>>a[i];
pos[a[i]]=i;
}
int ans=0;
for(int i=1;i<=n;i++){
if(a[i]==i) continue;
if(pos[i]==a[i]&&a[a[i]]==i) continue;
swap(a[pos[i]],a[a[i]]);
swap(pos[a[pos[i]]],pos[a[a[i]]]);
ans++;
}
cout<<ans<<"\n";
}

F - Kosuke’s Sloth

递推数列具有模周期性,找到第一个循环节中的下标再乘n即可

1
2
3
4
5
6
7
8
9
10
11
12
13
void solve(){
int n,k;cin>>n>>k;
f[1]=f[2]=1;
int pos=0;
for(int i=1;;i++){
if(i>=3) f[i]=(f[i-1]+f[i-2])%k;
if(f[i]%k==0){
pos=i;
break;
}
}
cout<<(pos%mod)*(n%mod)%mod<<"\n";
}

Welcome to my other publishing channels