Codeforces Round #615 (Div. 3) A-F

传送门

这场比较简单,简单的题就不说题意了。

A.

问加 n n n个数,能否使 a , b , c a,b,c a,b,c相等。

直接先加到相等再看看模 3 3 3是否为 0 0 0即可。

//#pragma GCC optimize(2)
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#include<ctime>
#include<cstdlib>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define pb push_back
#define mk make_pair
#define Mid (tr[u].l+tr[u].r>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define db puts("---")
using namespace std;

//void rd_cre() { freopen("d://dp//data.txt","w",stdout); srand(time(NULL)); }
//void rd_ac() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//AC.txt","w",stdout); }
//void rd_wa() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//WA.txt","w",stdout); }

typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;

const int N=1000010,mod=1e9+7,INF=0x3f3f3f3f;
const double eps=1e-6;

int a[10];

int main()
{
//	ios::sync_with_stdio(false);
//	cin.tie(0);

    int _; scanf("%d",&_);
    while(_--)
    {
        int n;
        scanf("%d%d%d%d",&a[1],&a[2],&a[3],&n);
        sort(a+1,a+1+3);
        n-=a[3]-a[1];
        n-=a[3]-a[2];
        if(n<0||n%3!=0) puts("NO");
        else puts("YES");
    }
	return 0;
}
/*

*/

B.

只能往右或者上走,求字典序最小的走法。

排序后判一下是否有不合法的点,让后每次都先右后上就行。

//#pragma GCC optimize(2)
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#include<ctime>
#include<cstdlib>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define pb push_back
#define mk make_pair
#define Mid (tr[u].l+tr[u].r>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define db puts("---")
using namespace std;

//void rd_cre() { freopen("d://dp//data.txt","w",stdout); srand(time(NULL)); }
//void rd_ac() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//AC.txt","w",stdout); }
//void rd_wa() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//WA.txt","w",stdout); }

typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;

const int N=100010,mod=1e9+7,INF=0x3f3f3f3f;
const double eps=1e-6;

int n;
PII p[N];

bool check()
{
    for(int i=2;i<=n;i++) if(p[i].X<p[i-1].X||p[i].Y<p[i-1].Y) return false;
    return true;
}

int main()
{
//	ios::sync_with_stdio(false);
//	cin.tie(0);

    int _; scanf("%d",&_);
    while(_--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++) scanf("%d%d",&p[i].X,&p[i].Y);
        sort(p+1,p+1+n);
        if(check())
        {
            puts("YES");
            int sx=0,sy=0,st=1;
            while(st<=n)
            {
                for(int i=sx;i<p[st].X;i++) printf("R");
                for(int i=sy;i<p[st].Y;i++) printf("U");
                sx=p[st].X; sy=p[st].Y;
                st++;
            }
            puts("");
        }
        else puts("NO");
    }




	return 0;
}
/*

*/

C.

找三个数 a , b , c a,b,c a,b,c,且其都大于等于 2 2 2,且 a ! = b , b ! = c , a ! = c a!=b,b!=c,a!=c a!=b,b!=c,a!=c,且 a ∗ b ∗ c = n a*b*c=n abc=n

直接把 n n n质因子分解,让后按照质因子的幂次从 1 , 2 , 3... 1,2,3... 1,2,3...累乘起来,取两个数,第三个数直接算即可。

//#pragma GCC optimize(2)
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#include<ctime>
#include<cstdlib>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define pb push_back
#define mk make_pair
#define Mid (tr[u].l+tr[u].r>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define db puts("---")
using namespace std;

//void rd_cre() { freopen("d://dp//data.txt","w",stdout); srand(time(NULL)); }
//void rd_ac() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//AC.txt","w",stdout); }
//void rd_wa() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//WA.txt","w",stdout); }

typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;

const int N=100010,mod=1e9+7,INF=0x3f3f3f3f;
const double eps=1e-6;

int n;
map<int,int>mp;

void divide()
{
    for(int i=2;i<=n/i;i++)
        if(n%i==0)
        {
            while(n%i==0) mp[i]++,n/=i;
        }
    if(n>1) mp[n]++;
}

int main()
{
//	ios::sync_with_stdio(false);
//	cin.tie(0);

    int _; scanf("%d",&_);
    while(_--)
    {
        scanf("%d",&n);
        int nn=n;
        mp.clear();
        divide();
        int a,b,c;
        a=-1; b=-1; c=-1;
        vector<int>v;
        for(auto x:mp)
        {
            int now=x.X,cnt=1;
            while(cnt<=x.Y)
            {
                v.pb(now);
                now*=x.X;
                x.Y-=cnt;
                cnt++;
            }
        }

        if(v.size()<2) puts("NO");
        else
        {
            a=v[0],b=v[1],c=nn/a/b;
            if(c==1||c==a||c==b) { puts("NO"); continue; }
            puts("YES");
            printf("%d %d %d\n",a,b,c);
        }
    }





	return 0;
}
/*

*/



D.

序列初始为空,每次加入一个数 y y y,可以将这个数 + x , − x +x,-x +x,x,可以执行无限次,但是 y y y不能小于 0 0 0。求每次加入数后的最大 m e x mex mex

因为求最大的 m e x mex mex,所以肯定是将这个数从小往大的填。我们将 y   m o d   x y\bmod x ymodx,这个时候可以将其看成一个系,即 y   m o d   x + k ∗ x y\bmod x +k*x ymodx+kx,我们从这个系的底开始向上填即可。由于 y   m o d   x < x y\bmod x<x ymodx<x只需要开一个数组记录一下当前底是多少,每次如果用掉了就让这个底 + x +x +x即可。
但是注意不能一直加,这样的话会 r e re re,所以我们设置一个上限就好啦,因为 m e x mex mex不会一直大下去的。

//#pragma GCC optimize(2)
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#include<ctime>
#include<cstdlib>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define pb push_back
#define mk make_pair
#define Mid (tr[u].l+tr[u].r>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define db puts("---")
using namespace std;

//void rd_cre() { freopen("d://dp//data.txt","w",stdout); srand(time(NULL)); }
//void rd_ac() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//AC.txt","w",stdout); }
//void rd_wa() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//WA.txt","w",stdout); }

typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;

const int N=10000010,mod=1e9+7,INF=0x3f3f3f3f;
const double eps=1e-6;

int q,x;
int pos[N],st[N];
int ans=0;

int main()
{
//	ios::sync_with_stdio(false);
//	cin.tie(0);

    scanf("%d%d",&q,&x);
    for(int i=0;i<=x;i++) pos[i]=i;
    while(q--)
    {
        int v; scanf("%d",&v);
        v%=x; if(pos[v]<8000000) pos[v]+=x;  v=pos[v]-x;
        st[v]=1;
        while(st[ans]) ans++;
        printf("%d\n",ans);
    }







	return 0;
}
/*

*/


E.

给你个矩阵,每次可以修改一个数为 1 , n ∗ m 1,n*m 1,nm之间的任何数,也可以将一列向上循环移动一位,这两个花费都是 1 1 1,求变成如下矩阵的最小花费。
在这里插入图片描述

乍一看不是很好做,但是仔细一想就是个大水题。
因为移动只涉及列,所以每一列是独立的,我们独立统计每一列就好啦。
只考虑一列,我们可以记录一下这一列的每个数,这个数到他应该到的位置需要移动几次,假设移动 x x x次,让后我们让 c n t [ x ] + + cnt[x]++ cnt[x]++,之后就枚举移动几次,假设移动 i i i次,让后答案就是 n − c n t [ x ] + i n-cnt[x]+i ncnt[x]+i

//#pragma GCC optimize(2)
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#include<ctime>
#include<cstdlib>
#define X first
#include<assert.h>
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define pb push_back
#define mk make_pair
#define Mid (tr[u].l+tr[u].r>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define db puts("---")
using namespace std;

//void rd_cre() { freopen("d://dp//data.txt","w",stdout); srand(time(NULL)); }
//void rd_ac() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//AC.txt","w",stdout); }
//void rd_wa() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//WA.txt","w",stdout); }

typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;

const int N=2000010,mod=1e9+7,INF=0x3f3f3f3f;
const double eps=1e-6;

int n,m;
int a[N];
vector<int>v[N];

int solve(int j)
{
    for(int i=0;i<=n;i++) a[i]=0;
    for(int i=0;i<n;i++)
    {
        if(v[i][j]%m!=j||v[i][j]>=n*m) continue;
        int pos=v[i][j]/m;
        int cnt=0;
        if(pos>i) cnt=i+n-pos;
        else cnt=i-pos;
        a[cnt]++;
    }
    int ans=INF;
    for(int i=0;i<=n;i++) ans=min(ans,i+n-a[i]);
    return ans;
}

int main()
{
//	ios::sync_with_stdio(false);
//	cin.tie(0);

    scanf("%d%d",&n,&m);
    for(int i=0;i<n;i++)
        for(int j=0;j<m;j++)
        {
            int x; scanf("%d",&x); x--;
            v[i].pb(x);
        }
    int ans=0;
    for(int i=0;i<m;i++) ans+=solve(i);
    printf("%d\n",ans);






	return 0;
}
/*

*/

F.

求三个点,这三个点之间的边最多。

众所周知, c f cf cf就是猜结论的比赛。所以直接选两个点为直径的两端,之后选的一个点就是到直径边最多的点即可。
实现的话我以前写过求直径上所有点的,所以直接贴过来了,知道所有点了之后,放进队列, b f s bfs bfs d i s dis dis,选个 d i s dis dis最大的即可。

//#pragma GCC optimize(2)
#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<map>
#include<cmath>
#include<cctype>
#include<vector>
#include<set>
#include<queue>
#include<algorithm>
#include<sstream>
#include<ctime>
#include<cstdlib>
#define X first
#define Y second
#define L (u<<1)
#define R (u<<1|1)
#define pb push_back
#define mk make_pair
#define Mid (tr[u].l+tr[u].r>>1)
#define Len(u) (tr[u].r-tr[u].l+1)
#define random(a,b) ((a)+rand()%((b)-(a)+1))
#define db puts("---")
using namespace std;

//void rd_cre() { freopen("d://dp//data.txt","w",stdout); srand(time(NULL)); }
//void rd_ac() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//AC.txt","w",stdout); }
//void rd_wa() { freopen("d://dp//data.txt","r",stdin); freopen("d://dp//WA.txt","w",stdout); }

typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;

const int N=1000010,M=N*2,mod=1e9+7,INF=0x3f3f3f3f;
const double eps=1e-6;

int n,root;
map<PII,int>mp;
vector<int>v[N];
int ans[N],d[N],dis[N];
int e[M],ne[M],h[N],w[M],idx;
int depth[N],res;
bool st[N];
int ed,flag,pre[N];

void add(int a,int b,int c)
{
    e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;
}

void dfs_dep(int u,int fa)
{
    depth[u]=depth[fa]+1;
    for(auto x:v[u])
    {
        int ver=x;
        if(ver==fa) continue;
        dfs_dep(ver,u);
    }
}

void dfs(int u,int fa)
{
    if(flag) return;
    if(u==ed) { flag=1; return; }
    for(auto x:v[u])
    {
        if(x==fa) continue;
        pre[x]=u;
        dfs(x,u);
        if(flag) return;
        pre[x]=0;
    }
}

void dfs_add(int u,int fa)
{
    for(auto x:v[u])
    {
        if(x==fa) continue;
        ans[x]=mp[{x,u}];
        dfs_add(x,u);
    }
}

void dfs_d(int u,int fa)
{
    int mx=0;
    for(auto x:v[u])
    {
        if(x==fa) continue;
        dfs_d(x,u);
        mx=max(mx,depth[x]+1);
    }
    depth[u]=mx;
}

int main()
{
//	ios::sync_with_stdio(false);
//	cin.tie(0);

    memset(h,-1,sizeof(h));
    scanf("%d",&n);
    for(int i=1;i<=n-1;i++)
    {
        int a,b; scanf("%d%d",&a,&b);
        v[a].pb(b),v[b].pb(a);
    }
    dfs_dep(1,0);
    int id=0,mx=-1;
    for(int i=1;i<=n;i++) if(depth[i]>mx) mx=depth[i],root=i;
    memset(depth,0,sizeof(depth));
    dfs_dep(root,0); mx=-1;
    for(int i=1;i<=n;i++) if(depth[i]>mx) mx=depth[i],ed=i;
    dfs(root,0);
    vector<int>vv; vv.pb(ed);
    pre[root]=0;
    while(pre[ed]!=0) vv.pb(pre[ed]),ed=pre[ed];
    queue<int>q;
    memset(dis,0x3f,sizeof(dis));
    memset(st,false,sizeof(st));
    for(int i=0;i<vv.size();i++) { int x=vv[i]; q.push(x),st[x]=1,dis[x]=0; }
    while(q.size())
    {
        int t=q.front(); q.pop();
        for(int i=0;i<v[t].size();i++)
        {
            int x=v[t][i];
            if(st[x]) continue;
            dis[x]=dis[t]+1;
            st[x]=1;
            q.push(x);
        }
    }
    int x=vv[0],y=vv[vv.size()-1],z=vv[1];
    int mmx=0;
    for(int i=1;i<=n;i++) if(dis[i]>mmx&&dis[i]!=INF) mmx=dis[i],z=i;
    printf("%d\n",mmx+(int)vv.size()-1);
    printf("%d %d %d\n",x,y,z);

	return 0;
}
/*
12
1 2
2 12
2 3
12 7
12 6
12 5
3 4
1 11
11 8
11 9
11 10
*/





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值