Codeforces Round #553 (Div. 2) Solution

Codeforces Round #553 (Div. 2) Solution

今天早上开的一把\(\rm vp\),前四题很水,看了\(\rm E,F\)之后我去写了\(\rm F\),然后还没调出来血亏...赛后才发现\(\rm E\)是真的水...


比赛传送门:https://codeforces.com/contest/1151

A. Maxim and Biology

https://codeforces.com/contest/1151/problem/A

直接暴力就好了。

#include<bits/stdc++.h>
using namespace std;

#define int long long 

void read(int &x) {
    x=0;int f=1;char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
    for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
}
 
void print(int x) {
    if(x<0) putchar('-'),x=-x;
    if(!x) return ;print(x/10),putchar(x%10+48);
}
void write(int x) {if(!x) putchar('0');else print(x);putchar('\n');}

#define lf long double
#define ll long long 

#define pii pair<int,int >
#define vec vector<int >

#define pb push_back
#define mp make_pair
#define fr first
#define sc second

#define FOR(i,l,r) for(int i=l,i##_r=r;i<=i##_r;i++) 

const int maxn = 2e5+10;
const int inf = 1e9;
const lf eps = 1e-12;
const int mod = 1e9+7;

int n;
char s[maxn];

int get(int a,int b) {
    return min(abs(a-b),26-max(a,b)+min(a,b));
}

signed main() {
    read(n);scanf("%s",s+1);
    int ans=1e9;
    for(int i=1;i<=n-3;i++) ans=min(ans,get(s[i],'A')+get(s[i+1],'C')+get(s[i+2],'T')+get(s[i+3],'G'));
    write(ans);
    return 0;
}

B. Dima and a Bad XOR

https://codeforces.com/contest/1151/problem/B

这题很奇怪...我只会乱搞...

我们考虑每一列随机一个数出来,随机一万次,错误的概率趋近于\(0\)了。

#include<bits/stdc++.h>
using namespace std;

#define int long long 

void read(int &x) {
    x=0;int f=1;char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
    for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
}
 
void print(int x) {
    if(x<0) putchar('-'),x=-x;
    if(!x) return ;print(x/10),putchar(x%10+48);
}
void write(int x) {if(!x) putchar('0');else print(x);putchar('\n');}

#define lf long double
#define ll long long 

#define pii pair<int,int >
#define vec vector<int >

#define pb push_back
#define mp make_pair
#define fr first
#define sc second

#define FOR(i,l,r) for(int i=l,i##_r=r;i<=i##_r;i++) 

const int maxn = 2e5+10;
const int inf = 1e9;
const lf eps = 1e-12;
const int mod = 998244353;
const int inv2 = 499122177;

int n,m,a[505][505],t[505];

signed main() {
    srand(time(0));
    read(n),read(m);FOR(i,1,n) FOR(j,1,m) read(a[i][j]);
    for(int i=1;i<=20000;i++) {
        int res=0;
        for(int j=1;j<=n;j++) res^=a[j][t[j]=rand()%m+1];
        if(res) {
            puts("TAK");
            for(int k=1;k<=n;k++) printf("%d ",t[k]);
            puts("");return 0;
        }
    }puts("NIE");
    return 0;
}

C. Problem for Nazar

https://codeforces.com/contest/1151/problem/C

倍增,然后按题意模拟。

#include<bits/stdc++.h>
using namespace std;

#define int long long 

void read(int &x) {
    x=0;int f=1;char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
    for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
}
 
void print(int x) {
    if(x<0) putchar('-'),x=-x;
    if(!x) return ;print(x/10),putchar(x%10+48);
}
void write(int x) {if(!x) putchar('0');else print(x);putchar('\n');}

#define lf long double
#define ll long long 

#define pii pair<int,int >
#define vec vector<int >

#define pb push_back
#define mp make_pair
#define fr first
#define sc second

#define FOR(i,l,r) for(int i=l,i##_r=r;i<=i##_r;i++) 

const int maxn = 2e5+10;
const int inf = 1e9;
const lf eps = 1e-12;
const int mod = 1e9+7;
const int inv2 = 5e8+4;

int a[2];

int sum(int x,int y,int t) {
    int qwe=(y-x+1)%mod;
    x<<=1,y<<=1;if(t) x--,y--;
    x%=mod,y%=mod;
    return 1ll*(x+y)*qwe%mod*inv2%mod;
}

int solve(int r) {
    int tot=0,now=1,kd=1;
    int ans=0;a[0]=a[1]=1;
    while(tot<r) {
        if(tot+now>r) ans+=sum(a[kd],a[kd]+r-now,kd);
        else ans+=sum(a[kd],a[kd]+now-1,kd);
        a[kd]+=now,tot+=now,now<<=1,kd^=1;
    }return (ans%mod+mod)%mod; 
}

signed main() {
    int l,r;read(l),read(r);
    write((solve(r)-solve(l-1)+mod)%mod);
    return 0;
}

D. Stas and the Queue at the Buffet

https://codeforces.com/contest/1151/problem/D

把式子拆开就是:
\[ nb_i-a_i+j\cdot (a_i-b_i) \]
所以直接贪心的按\(a_i-b_i\)排序就好了。

#include<bits/stdc++.h>
using namespace std;

#define int long long 

void read(int &x) {
    x=0;int f=1;char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
    for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
}
 
void print(int x) {
    if(x<0) putchar('-'),x=-x;
    if(!x) return ;print(x/10),putchar(x%10+48);
}
void write(int x) {if(!x) putchar('0');else print(x);putchar('\n');}

#define lf long double
#define ll long long 

#define pii pair<int,int >
#define vec vector<int >

#define pb push_back
#define mp make_pair
#define fr first
#define sc second

#define FOR(i,l,r) for(int i=l,i##_r=r;i<=i##_r;i++) 

const int maxn = 2e5+10;
const int inf = 1e9;
const lf eps = 1e-12;
const int mod = 998244353;
const int inv2 = 499122177;

int n,a[maxn],b[maxn],t[maxn];

signed main() {
    read(n);FOR(i,1,n) read(a[i]),read(b[i]),t[i]=a[i]-b[i];
    sort(t+1,t+n+1);int res=0;
    for(int i=n;i;i--) res+=t[n-i+1]*i;
    for(int i=1;i<=n;i++) res+=-1*a[i]+n*b[i];
    write(res);
    return 0;
}

E. Number of Components

https://codeforces.com/contest/1151/problem/E

注意到森林的连通块个数\(=\)点数\(-\)边数。

枚举每个点和每条边的贡献就行。

#include<bits/stdc++.h>
using namespace std;

#define int long long 

void read(int &x) {
    x=0;int f=1;char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
    for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
}
 
#define ll long long

void print(ll x) {
    if(x<0) putchar('-'),x=-x;
    if(!x) return ;print(x/10),putchar(x%10+48);
}
void write(ll x) {if(!x) putchar('0');else print(x);putchar('\n');}

#define lf double

#define pii pair<int,int >
#define vec vector<int >

#define pb push_back
#define mp make_pair
#define fr first
#define sc second

#define FOR(i,l,r) for(int i=l,i##_r=r;i<=i##_r;i++) 

const int maxn = 2e5+10;
const int inf = 1e9;
const lf eps = 1e-8;

ll ans,s;
int n,a[maxn];

int c(int x) {return x*(x-1)/2+x;}

signed main() {
    read(n);FOR(i,1,n) read(a[i]),ans+=c(n)-c(n-a[i])-c(a[i]-1);
    FOR(i,1,n-1) {
        int l=min(a[i],a[i+1]),r=max(a[i],a[i+1]);
        ans-=1ll*l*(n-r+1);
    }write(ans);
    return 0;
}

F. Sonya and Informatics

https://codeforces.com/contest/1151/problem/F

这是这场唯一有点难度的题了...可能是我太菜了吧

注意到最终状态一定是前面\(k\)\(0\),后面全是\(1\),其中\(k\)为一开始\(0\)的个数。

我们考虑一个暴力的\(dp\),设\(f[i][j]\)表示进行了\(i\)次操作,前\(k\)个位置有\(j\)\(0\)的情况总数。

然后转移枚举几种情况:

  • 前面(指前\(k\)个位置)的一个白色\((0)\)和后面的一个黑色\((1)\) \(\rm swap\),那么前面的白色个数\(-1\),方案数为\(i(n-k-(k-i))\)
  • 前面的黑色和后面的白色换,那么白色个数\(+1\),方案数和上面同理。
  • 同样的颜色换,白色个数不变。
  • 前面的和前面的换或后面和后面换,白色个数不变。

这样转移复杂度为\(O(nk)\),但是\(k\)太大了过不了。

注意到\(n\)只有\(100\)我们可以用矩阵优化上面的转移,复杂度\(O(n^3\log k)\)

#include<bits/stdc++.h>
using namespace std;

#define int long long 

void read(int &x) {
    x=0;int f=1;char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
    for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
}
 
void print(int x) {
    if(x<0) putchar('-'),x=-x;
    if(!x) return ;print(x/10),putchar(x%10+48);
}
void write(int x) {if(!x) putchar('0');else print(x);putchar('\n');}

#define lf long double
#define ll long long 

#define pii pair<int,int >
#define vec vector<int >

#define pb push_back
#define mp make_pair
#define fr first
#define sc second

#define FOR(i,l,r) for(int i=l,i##_r=r;i<=i##_r;i++) 

const int maxn = 2e5+10;
const int inf = 1e9;
const lf eps = 1e-12;
const int mod = 1e9+7;

int add(int x,int y) {return x+y>=mod?x+y-mod:x+y;}
int del(int x,int y) {return x-y<0?x-y+mod:x-y;}
int mul(int x,int y) {return 1ll*x*y-1ll*x*y/mod*mod;}
void inc(int &x,int y) {x+=y;x%=mod;}

int n,k,a[maxn],res,c;

int qpow(int a,int x) {
    int res=1;
    for(;x;x>>=1,a=1ll*a*a%mod) if(x&1) res=1ll*res*a%mod;
    return res;
}

struct Matrix {
    int a,b,r[110][110];

    Matrix () {a=b=0,memset(r,0,sizeof r);}
    
    Matrix operator * (const Matrix &t) const {
        Matrix res;res.a=a,res.b=t.b;
        for(int i=0;i<=a;i++)
            for(int j=0;j<=t.b;j++)
                for(int k=0;k<=b;k++)
                    res.r[i][j]=add(res.r[i][j],mul(r[i][k],t.r[k][j]));
        return res;
    }
}tr,ans;

signed main() {
    read(n),read(k);
    for(int i=1;i<=n;i++) read(a[i]),res+=!(a[i]&1);
    for(int i=1;i<=res;i++) c+=!a[i];
    ans.a=0,ans.b=res;ans.r[0][c]=1;tr.a=tr.b=res;
    for(int i=0;i<=res;i++) {
        int lw=i,lb=res-i,rw=res-lw,rb=n-res-lb;
        if(i!=res) inc(tr.r[i][i+1],lb*rw%mod);
        if(i!=0) inc(tr.r[i][i-1],lw*rb%mod);
        inc(tr.r[i][i],(res*(res-1)+(n-res)*(n-res-1))%mod*qpow(2,mod-2)%mod);
        inc(tr.r[i][i],(lw*lb+rw*rb)%mod);
    }
    int x=k,f=0;
    for(;x;x>>=1,tr=tr*tr) if(x&1) ans=ans*tr;
    FOR(i,0,res) f=(f+ans.r[0][i])%mod;write(ans.r[0][res]*qpow(f,mod-2)%mod);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/hbyer/p/11025016.html