#16简单题

[AGC004C] AND Grid

题面

题目中有个重要条件:第一行,第一列,最后一行,最后一列都没有涂色点。可以很快得到一种构造方法,在第一张图中将第一列和奇数行涂色,在第二张图中将最后一列和偶数行涂色。此时两张图染色的格子没有交。再将所有在原图中染色的点在两张图中都染色即可。

点击查看代码
#include<bits/stdc++.h>
#define ll long long
#define pii pair<int,int>
#define pdi pair<double,int>
#define pb push_back
#define eps 1e-9
#define mp make_pair
using namespace std;
const int inf=1e9;
namespace IO{
    template<typename T>
    inline void read(T &x){
        x=0;
        int f=1;
        char ch=getchar();
        while(ch>'9'||ch<'0'){
            if(ch=='-'){
                f=-1;
    }
            ch=getchar();
        }
        while(ch>='0'&&ch<='9'){
            x=x*10+(ch-'0');
            ch=getchar();
        }
        x=(f==1?x:-x);
    }
    template<typename T>
    inline void write(T x){
        if(x<0){
            putchar('-');
            x=-x;
        }
        if(x>=10){
            write(x/10);
        }
        putchar(x%10+'0');
    }
    template<typename T>
    inline void write_endl(T x){
        write(x);
        putchar('\n');
    }
    template<typename T>
    inline void write_space(T x){
        write(x);
        putchar(' ');
    }
}
using namespace IO;
const int N=510;
int n,m;
char s[N][N];
void solve(){
    read(n),read(m);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            s[i][j]=getchar();
            while(s[i][j]!='.'&&s[i][j]!='#'){
                s[i][j]=getchar();
            }
        }
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(j==m){
                putchar('.');
                continue;
            }
            if(j==1||i%2||s[i][j]=='#'){
                putchar('#');
            }
            else{
                putchar('.');
            }
        }
        putchar('\n');
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(j==1){
                putchar('.');
                continue;
            }
            if(j==m||i%2==0||s[i][j]=='#'){
                putchar('#');
            }
            else{
                putchar('.');
            }
        }
        putchar('\n');
    }
}
signed main(){
    #ifndef ONLINE_JUDGE
        freopen("1.in","r",stdin);
        freopen("1.out","w",stdout);
    #endif
    int t=1;
    while(t--){
        solve();
    }
    return 0;
}

Returning Home

题面

容易想到在传送点间建图,再求最短路。但是边数太大,考虑优化建图。

注意到一件事,若 \(i,j\) 间存在一个中间点 \(k\)\(i\rightarrow k\rightarrow j\)\(i\rightarrow j\) 是本质相同的。所以可以按两维分别将点排序,从排序后的第 \(i\) 个点连边向 第 \(i+1\) 个点。这是边数优化到了 \(O(m)\) 级别,复杂度为 \(O(m\log m)\)

点击查看代码
#include<bits/stdc++.h>
#define ull unsigned long long
#define ll long long
#define pii pair<int,int>
#define pdi pair<double,int>
#define pb push_back
#define eps 1e-9
#define mp make_pair
using namespace std;
const int inf=1e9;
namespace IO{
    template<typename T>
    inline void read(T &x){
        x=0;
        int f=1;
        char ch=getchar();
        while(ch>'9'||ch<'0'){
            if(ch=='-'){
                f=-1;
    }
            ch=getchar();
        }
        while(ch>='0'&&ch<='9'){
            x=x*10+(ch-'0');
            ch=getchar();
        }
        x=(f==1?x:-x);
    }
    template<typename T>
    inline void write(T x){
        if(x<0){
            putchar('-');
            x=-x;
        }
        if(x>=10){
            write(x/10);
        }
        putchar(x%10+'0');
    }
    template<typename T>
    inline void write_endl(T x){
        write(x);
        putchar('\n');
    }
    template<typename T>
    inline void write_space(T x){
        write(x);
        putchar(' ');
    }
}
using namespace IO;
const int N=1e5+10;
int n,m,x[N],y[N],id[N],head[N],tot=1,dis[N],vis[N];
bool cmp1(int a,int b){
    return x[a]==x[b]?y[a]<y[b]:x[a]<x[b];
}
bool cmp2(int a,int b){
    return y[a]==y[b]?x[a]<x[b]:y[a]<y[b];
}
struct edge{
    int v,w,nxt;
}e[N<<2];
void add(int u,int v,int w){
    e[++tot].v=v;
    e[tot].w=w;
    e[tot].nxt=head[u];
    head[u]=tot;
}
void add_e(int u,int v,int w){
    add(u,v,w);
    add(v,u,w);
}
void solve(){
    read(n),read(m);
    int stx,sty,edx,edy;
    read(stx),read(sty),read(edx),read(edy);
    for(int i=1;i<=m;i++){
        read(x[i]),read(y[i]);
        id[i]=i;
    }
    sort(id+1,id+m+1,cmp1);
    for(int i=1;i<m;i++){
        add_e(id[i],id[i+1],min(abs(x[id[i]]-x[id[i+1]]),abs(y[id[i]]-y[id[i+1]])));
    }
    sort(id+1,id+m+1,cmp2);
    for(int i=1;i<m;i++){
        add_e(id[i],id[i+1],min(abs(x[id[i]]-x[id[i+1]]),abs(y[id[i]]-y[id[i+1]])));
    }
    priority_queue<pii>q;
    for(int i=1;i<=m;i++){
        dis[i]=min(abs(x[i]-stx),abs(y[i]-sty));
        q.push(mp(-dis[i],i));
    }
    while(q.size()){
        int u=q.top().second;
        q.pop();
        if(vis[u]){
            continue;
        }
        vis[u]=1;
        for(int i=head[u];i;i=e[i].nxt){
            int v=e[i].v,w=e[i].w;
            if(dis[v]>dis[u]+w){
                dis[v]=dis[u]+w;
                q.push(mp(-dis[v],v));
            }
        }
    }
    int ans=abs(stx-edx)+abs(sty-edy);
    for(int i=1;i<=m;i++){
        ans=min(ans,dis[i]+abs(edx-x[i])+abs(edy-y[i]));
    }
    write_endl(ans);
}
signed main(){
    #ifndef ONLINE_JUDGE
        freopen("1.in","r",stdin);
        freopen("1.out","w",stdout);
    #endif
    int t=1;
    while(t--){
        solve();
    }
    return 0;
}

[AGC037C] Numbers on a Circle

题面

将操作改为 \(b_i\rightarrow b_i-b_{i-1}-b_{i+1}\),若一个操作合法,则 \(b_i>b_{i-1}+b_{i+1}\)。当存在 \(b_i>a_i\) 且无法进行操作时,无解。最大的没有满足 \(b_i=a_i\) 的树肯定是可选的,使用优先队列维护选取过程。

点击查看代码
#include<bits/stdc++.h>
#define ull unsigned long long
#define int long long
#define pii pair<int,int>
#define pdi pair<double,int>
#define pb push_back
#define eps 1e-9
#define mp make_pair
using namespace std;
const int inf=1e9;
namespace IO{
    template<typename T>
    inline void read(T &x){
        x=0;
        int f=1;
        char ch=getchar();
        while(ch>'9'||ch<'0'){
            if(ch=='-'){
                f=-1;
    }
            ch=getchar();
        }
        while(ch>='0'&&ch<='9'){
            x=x*10+(ch-'0');
            ch=getchar();
        }
        x=(f==1?x:-x);
    }
    template<typename T>
    inline void write(T x){
        if(x<0){
            putchar('-');
            x=-x;
        }
        if(x>=10){
            write(x/10);
        }
        putchar(x%10+'0');
    }
    template<typename T>
    inline void write_endl(T x){
        write(x);
        putchar('\n');
    }
    template<typename T>
    inline void write_space(T x){
        write(x);
        putchar(' ');
    }
}
using namespace IO;
const int N=2e5+10;
int n,a[N],b[N];
void solve(){
    read(n);
    for(int i=1;i<=n;i++){
        read(a[i%n]);
    }
    for(int i=1;i<=n;i++){
        read(b[i%n]);
    }
    priority_queue<pii>q;
    for(int i=0;i<n;i++){
        if(b[i]<a[i]){
            puts("-1");
            return;
        }
        if(b[i]>a[i]){
            q.push(mp(b[i],i));
        }
    }
    int ans=0;
    while(q.size()){
        int i=q.top().second;
        q.pop();
        int del=b[i]-a[i],delta=b[(i-1+n)%n]+b[(i+1)%n];
        if(del/delta==0){
            write_endl(-1);
            return;
        }
        ans+=del/delta;
        b[i]-=del/delta*delta;
        if(b[i]>a[i]){
            q.push(mp(b[i],i));
        }
    }
    write_endl(ans);
}
signed main(){
    #ifndef ONLINE_JUDGE
        freopen("1.in","r",stdin);
        freopen("1.out","w",stdout);
    #endif
    int t=1;
    while(t--){
        solve();
    }
    return 0;
}

[COCI2020-2021#2] Sjekira

题面

贪心考虑,一个点如果权值小则让它多产生贡献,反之少产生贡献。

将删边转加边,将点按照点权排序。对于一个点,每次只和比它点权小的点合并。正确性显然,因为这样不会使得一条边两端的点权更大。可以用并查集维护连通块。

点击查看代码
#include<bits/stdc++.h>
#define ull unsigned long long
#define ll long long
#define pdi pair<double,int>
#define pii pair<int,int>
#define pb push_back
#define mp make_pair
#define eps 1e-9
using namespace std;
namespace IO{
    template<typename T>
    inline void read(T &x){
        x=0;
        int f=1;
        char ch=getchar();
        while(ch>'9'||ch<'0'){
            if(ch=='-'){
                f=-1;
    }
            ch=getchar();
        }
        while(ch>='0'&&ch<='9'){
            x=x*10+(ch-'0');
            ch=getchar();
        }
        x=(f==1?x:-x);
    }
    template<typename T>
    inline void write(T x){
        if(x<0){
            putchar('-');
            x=-x;
        }
        if(x>=10){
            write(x/10);
        }
        putchar(x%10+'0');
    }
    template<typename T>
    inline void write_endl(T x){
        write(x);
        putchar('\n');
    }
    template<typename T>
    inline void write_space(T x){
        write(x);
        putchar(' ');
    }
}
using namespace IO;
const int N=1e5+10;
int n,a[N],id[N],fa[N],vis[N];
ll ans=0;
vector<int>e[N];
int getfa(int u){
    if(fa[u]!=u){
        fa[u]=getfa(fa[u]);
    }
    return fa[u];
}
bool cmp(int x,int y){
    return a[x]<a[y];
}
signed main(){
    read(n);
    for(int i=1;i<=n;i++){
        read(a[i]);
        id[i]=fa[i]=i;
    }
    sort(id+1,id+n+1,cmp);
    for(int i=1,u,v;i<n;i++){
        read(u),read(v);
        e[u].pb(v);
        e[v].pb(u);
    }
    for(int i=1;i<=n;i++){
        int u=id[i];
        vis[u]=1;
        for(auto v:e[u]){
            if(!vis[v]){
                continue;
            }
            u=getfa(u),v=getfa(v);
            if(u!=v){
                ans+=a[u]+a[v];
                fa[v]=u;
                a[u]=max(a[u],a[v]);
            }
        }
    }
    write_endl(ans);
    return 0;
}

Kate and imperfection

题面

按照贪心的方法,我们先将所有的质数加入到集合中,接下来加入最小的未被加入过的数 \(4\),此时答案为 \(2\),加入 \(6\) 后,答案为 \(3\),但是我们不能加入 \(8\),这样答案会增大,但是加入 \(9\) 则不会。可以发现规律,\(i\) 在答案为 \(\frac{i}{mn}\) 时加入集合最大,其中 \(mn\) 表示 \(i\) 的最小质因子。

点击查看代码
#include<bits/stdc++.h>
#define ull unsigned long long
#define ll long long
#define pii pair<int,int>
#define pdi pair<double,int>
#define pb push_back
#define eps 1e-9
#define mp make_pair
using namespace std;
const int inf=1e9;
namespace IO{
    template<typename T>
    inline void read(T &x){
        x=0;
        int f=1;
        char ch=getchar();
        while(ch>'9'||ch<'0'){
            if(ch=='-'){
                f=-1;
    }
            ch=getchar();
        }
        while(ch>='0'&&ch<='9'){
            x=x*10+(ch-'0');
            ch=getchar();
        }
        x=(f==1?x:-x);
    }
    template<typename T>
    inline void write(T x){
        if(x<0){
            putchar('-');
            x=-x;
        }
        if(x>=10){
            write(x/10);
        }
        putchar(x%10+'0');
    }
    template<typename T>
    inline void write_endl(T x){
        write(x);
        putchar('\n');
    }
    template<typename T>
    inline void write_space(T x){
        write(x);
        putchar(' ');
    }
}
using namespace IO;
const int N=5e5+10;
int n,prime[N],min_ins[N],cnt,ans[N];
void solve(){
    read(n);
    min_ins[1]=1;
    for(int i=2;i<=n;i++){
        if(!min_ins[i]){
            min_ins[i]=1;
            prime[++cnt]=i;
        }
        for(int j=1;j<=cnt&&prime[j]*i<=n;j++){
            min_ins[prime[j]*i]=i;
            if(i%prime[j]==0){
                break;
            }
        }
        ans[min_ins[i]]++;
    }
    for(int cnt=1;cnt<=n;cnt++){
        for(int i=1;i<=ans[cnt];i++){
            write_space(cnt);
        }
    }
}
signed main(){
    #ifndef ONLINE_JUDGE
        freopen("1.in","r",stdin);
        freopen("1.out","w",stdout);
    #endif
    int t=1;
    while(t--){
        solve();
    }
    return 0;
}

Little Elephant and Broken Sorting

题面

已知期望是独立的,所以可以将期望逆序对数拆为每对数为逆序对的期望和。令 \(f_{i,j}\) 表示 \(p_i>p_j\) 的期望。初始若 \(p_i>p_j\),则 \(f_{i,j}=1\)。对于一次交换 \((x,y)\)\(\forall x\not=y\),则 \(f_{i,x}=f_{i,y}=0.5(f_{i,x}+f_{i,y}),f_{y,i}=f_{x,i}=0.5(f_{x,i}+f_{y,i})\)\(f_{x,y}=f_{y,x}=0.5\)

最后求所有的 \(i<j\)\(f_{i,j}\) 的和。

点击查看代码
#include<bits/stdc++.h>
#define ull unsigned long long
#define ll long long
#define pii pair<int,int>
#define pdi pair<double,int>
#define pb push_back
#define eps 1e-9
#define mp make_pair
using namespace std;
const int inf=1e9;
namespace IO{
    template<typename T>
    inline void read(T &x){
        x=0;
        int f=1;
        char ch=getchar();
        while(ch>'9'||ch<'0'){
            if(ch=='-'){
                f=-1;
    }
            ch=getchar();
        }
        while(ch>='0'&&ch<='9'){
            x=x*10+(ch-'0');
            ch=getchar();
        }
        x=(f==1?x:-x);
    }
    template<typename T>
    inline void write(T x){
        if(x<0){
            putchar('-');
            x=-x;
        }
        if(x>=10){
            write(x/10);
        }
        putchar(x%10+'0');
    }
    template<typename T>
    inline void write_endl(T x){
        write(x);
        putchar('\n');
    }
    template<typename T>
    inline void write_space(T x){
        write(x);
        putchar(' ');
    }
}
using namespace IO;
const int N=1010;
int a[N],n,m;
double f[N][N];
void solve(){
    read(n),read(m);
    for(int i=1;i<=n;i++){
        read(a[i]);
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            f[i][j]=(a[i]>a[j]);
        }
    }
    for(int i=1;i<=m;i++){
        int x,y;
        read(x),read(y);
        for(int j=1;j<=n;j++){
            f[j][x]=f[j][y]=(f[j][x]+f[j][y])/2;
            f[x][j]=f[y][j]=(f[x][j]+f[y][j])/2;
        }
        f[x][y]=f[y][x]=0.5;
    }
    double ans=0;
    for(int i=1;i<=n;i++){
        for(int j=i+1;j<=n;j++){
            ans+=f[i][j];
        }
    }
    cout<<fixed<<setprecision(10)<<ans<<'\n';
}
signed main(){
    #ifndef ONLINE_JUDGE
        freopen("1.in","r",stdin);
        freopen("1.out","w",stdout);
    #endif
    int t=1;
    while(t--){
        solve();
    }
    return 0;
}

Moderate Modular Mode

题面

分类讨论。

\(x>y\),当 \(n>x\) 时,\(y<n\),即 \(n\bmod x\equiv y\),则 \(n=y+kx,k\in \mathbb{Z}\) 是一个合法的解。

\(x=y\)\(n=x\) 是一个合法的解。

\(x<y\),注意到 \(y<2x\) 时,\(n=\frac{y+x}{2}\) 是一个合法的解。所以我们找到 \(d\),满足 \(d=kx,k\in \mathbb{Z},d<y\),令 \(n=d+\farc{y-d}{2}\) 即可。

点击查看代码
#include<bits/stdc++.h>
#define ull unsigned long long
#define ll long long
#define pii pair<int,int>
#define pdi pair<double,int>
#define pb push_back
#define eps 1e-9
#define mp make_pair
using namespace std;
const int inf=1e9;
namespace IO{
    template<typename T>
    inline void read(T &x){
        x=0;
        int f=1;
        char ch=getchar();
        while(ch>'9'||ch<'0'){
            if(ch=='-'){
                f=-1;
    }
            ch=getchar();
        }
        while(ch>='0'&&ch<='9'){
            x=x*10+(ch-'0');
            ch=getchar();
        }
        x=(f==1?x:-x);
    }
    template<typename T>
    inline void write(T x){
        if(x<0){
            putchar('-');
            x=-x;
        }
        if(x>=10){
            write(x/10);
        }
        putchar(x%10+'0');
    }
    template<typename T>
    inline void write_endl(T x){
        write(x);
        putchar('\n');
    }
    template<typename T>
    inline void write_space(T x){
        write(x);
        putchar(' ');
    }
}
using namespace IO;
int x,y;
void solve(){
    read(x),read(y);
    if(y<x){
        write_endl(x+y);
    }
    else if(y==x){
        write_endl(x);
    }
    else{
        int mul=y/x;
        int d=mul*x;
        write_endl(d+(y-d)/2);
    }
}
signed main(){
    #ifndef ONLINE_JUDGE
        freopen("1.in","r",stdin);
        freopen("1.out","w",stdout);
    #endif
    int t;
    read(t);
    while(t--){
        solve();
    }
    return 0;
}
posted @ 2023-10-29 20:40  luo_shen  阅读(6)  评论(0编辑  收藏  举报