Codeforces Round #615 (Div. 3)

QAQ

A. Collecting Coins

题意:

有三堆硬币,数目分别是abc,现在你手上还有n枚硬币,问能否通过合理分配n枚硬币到这三堆硬币里,使得这三堆硬币数目相同。

思路:

求所有硬币的和sumcheck一下sum是否是三的倍数且每一堆硬币的数目都小于等于sum/3

代码:

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

int main()
{
   int t;
   ll a,b,c,n;
   cin >> t;
   while(t--)
   {
       cin >> a >> b >> c >> n;
       ll sum = a+b+c+n;
       if(sum%3!=0)
       {
            printf("NO\n");continue;
       }


       sum/=3;
       if(a>sum||b>sum||c>sum)
        printf("NO\n");
       else
        printf("YES\n");
   }
    return  0;
}

B. Collecting Packages

题意:

在一个二维平面上有n个点,一个机器人从原点出发,只能往上或往右走,问机器人能否经过所有的点,如果可以输出最短路径。

思路:

可以将横坐标作为第一关键字,纵坐标作为第二关键字对所有点进行排序,然后暴力模拟即可。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
struct Point
{
    int x,y;
    Point(int _x=0,int _y =0):x(_x),y(_y){}
    bool operator <(const Point&b)
    {
        if(x==b.x)
            return y<b.y;
        return x<b.x;
    }
};
vector<Point>vec;
string ans;
bool solve(int n)
{
    int x = 0,y = 0;
    for(int i =0;i<n;i++)
    {
        int x1 = vec[i].x,y1 =vec[i].y;
        if(x1<x)
            return false;
        if(y1<y)
            return false;
        for(x;x<x1;x++)
            ans+='R';
        for(y;y<y1;++y)
            ans+='U';
    }
    return true;
}
int main()
{
   int t;
   cin >> t;
   while(t--)
   {
       ans = "";
       vec.clear();
       int n;
       cin >>n;
       int x,y;
       for(int i = 0;i<n;++i)
       {
            cin >>x >>y;
            vec.push_back(Point(x,y));
       }
       sort(vec.begin(),vec.end());
      if(solve(n))
      {
          printf("YES\n");
          cout << ans << "\n";
      }
      else
        printf("NO\n");

   }
    return  0;
}

C .Product of Three Numbers

题意:

输入一个数n,问能不能拆分成三个大于2且完全不同的数abc,且a*b*c = n;

思路:

可以对n进行素数拆分,然后分类讨论即可。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
struct Prime
{
    int x,n;
    Prime() {}
    Prime(int _x,int _n):x(_x),n(_n) {}

};
vector<Prime>vec;
ll qp(ll x,ll n)
{
    ll res = 1;
    while(n>0)
    {
        if(n&1)res = res*x;
        x = x*x;
        n>>=1;
    }
    return res;
}
void solve(ll n)
{
    ll tmp = n;
    for(int i = 2; i*i<=n; ++i)
    {
        int cnt = 0;
        while(n%i==0)
        {
            cnt++;
            n/=i;
        }
        if(cnt>0)
            vec.push_back(Prime(i,cnt));
    }
    if(n!=1)
        vec.push_back(Prime(n,1));
//    int len = vec.size();
//    cout << len << endl;
//    for(int i =  0;i<len;++i)
//    {
//        cout << vec[i].x<< " " << vec[i].n << "\n";
//    }
    ll a=1,b=1,c=1;
    if(vec.size()>=3)
    {
        printf("YES\n");
        a = qp(vec[0].x,vec[0].n);
        b = qp(vec[1].x,vec[1].n);
        c = tmp/(a*b);
        cout << a << " " <<b << " " << c << "\n";
        return ;
    }
    if(vec.size()==2)
    {
        if(vec[0].n<2&&vec[1].n<2)
        {
            printf("NO\n");
            return ;
        }
        if(vec[0].n<vec[1].n)
            swap(vec[0],vec[1]);
       a = vec[0].x;
       b = vec[1].x;
       c = tmp/(a*b);
       if(c!=a&&c!=b)
       {
           printf("YES\n");
            cout << a << " " <<b << " " << c << "\n";
            return ;
       }
       else
        printf("NO\n");
       return ;


    }
    if(vec.size()==1)
    {
        if(vec[0].n<6)
        {
            printf("NO\n");
            return ;
        }
        a = vec[0].x;
        b = vec[0].x*vec[0].x;
        c = tmp/(a*b);
        printf("YES\n");
        cout << a << " " <<b << " " << c << "\n";
        return ;
    }
    printf("NO\n");
    return;
}
int main()
{
    //freopen("out.txt","w",stdout);
    int t;
    cin >> t;
    while(t--)
    {
        vec.clear();
        ll n;
        cin >> n;
        solve(n);
    }

    return  0;
}

D. MEX maximizing

题意:

定义一个数组的MEX为数组中第一个未出现的数,开始给你一个空数组以及一个数x,并伴有q次查询,每次查询输入一个数,你可以把这个数加上x无数次或者减x无数次,然后将它插入到数组中,使得每次插入后所得MEX最大。

思路:

首先,(ans-x)%x = ans%x = (ans+x)%x,因此我们就可以用一个数组cnt去模拟上面的数组了,首先对于每一次查询,它的答案不可能比上次查询要小,对于每次输入进来的那个数a,我们可以cnt[a%x]++,这个思路是把原先的一维数轴根据x分为若干段,对于a来说,无论它如何变化,它在某一段中的相对位置不会改变,这个位置也就是a%x,因此,我们可以开始从上一次查询的结果开始,不断循环,查询到底是那一段的那个位置缺失,这个数就是答案。

代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 4e5+10;
int num[maxn];
int main()
{
    int q,x,a;
    scanf("%d %d",&q,&x);
    int ans = 0;
    while(q--)
    {
        scanf("%d",&a);
        num[a%x]++;
        while(1)
        {
            if(num[ans%x]==0)
                break;
            num[ans%x]--;
            ++ans;
        }
        cout << ans << "\n";
    }
    return 0;
}

E. Obtain a Permutation

题意:

给你一个n*m的矩阵,定义一个move,在一个move你可以进行两种操作,一是选择矩阵中的任何一个元素将他替换成另一个值,二是选择任意一列将他的所有元素循环向上移动一位,问将该矩阵变成

 

 

 

所需要的最小move数。

思路:

首先,通过题意我们可以知道,每一列都是独立的,即对这一列的操作是不会影响到其他列的。因此,我们可以一列一列分开计算。对于某一列的某个元素,我们根据它的位置就可以知道这个位置的值应该是什么,我们枚举这一列的所有元素,假如这个元素是属于这一列的元素,我们可以计算出使它到它应该去的位置所需要的操作数,接下来,枚举操作数,不能移动得到的元素就只能更改了,对于每一个操作数,更新答案即可。

代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 4e5+10;
int num[maxn];
int main()
{
    int q,x,a;
    scanf("%d %d",&q,&x);
    int ans = 0;
    while(q--)
    {
        scanf("%d",&a);
        num[a%x]++;
        while(1)
        {
            if(num[ans%x]==0)
                break;
            num[ans%x]--;
            ++ans;
        }
        cout << ans << "\n";
    }
    return 0;
}

F. Three Paths on a Tree

题意:

给你一颗有n个结点的树,让你求树上三点a,b,c,使ab,bcca,这三条路径所经历的不重复的边数最多。

思路:

首先,这三个点一定有两个端点是在树的直径上,这里通过两次bfs求树的直径,然后枚举c点,因为每个点到两个端点的距离已经通过两次bfs得到,但要注意c不能与a,b点相同。

得到结果除2就是最终答案。

代码:

#include <bits/stdc++.h>
using namespace std;
const int maxn =2e5+10;
vector<int> a[maxn];
int n,vis[maxn],dis1[maxn],dis2[maxn],dis[maxn],pos;
void bfs(int x)
{
    memset(vis,0,sizeof(vis));
    memset(dis,0,sizeof(dis));
    pos = x;
    vis[x] = 1,dis[x] = 0;
    queue<int>q;
    q.push(x);
    while(!q.empty())
    {
        int u = q.front();
        q.pop();
        for(int i = 0;i<a[u].size();++i)
        {
            if(!vis[a[u][i]])
            {
                vis[a[u][i]] = 1;
                dis[a[u][i]] = dis[u]+1;
                q.push(a[u][i]);
                if(dis[a[u][i]]>dis[pos]) pos=a[u][i];
            }
        }
    }
}
int  main()
{
    scanf("%d",&n);
    int u,v;
    for(int i = 1;i<n;++i)
    {
        scanf("%d %d",&u,&v);
        a[u].push_back(v);
        a[v].push_back(u);
    }
    int a,b,c;
    bfs(1);a = pos;
    
    bfs(pos);b= pos;
    for(int i = 1;i<=n;++i)
        dis1[i] = dis[i];
    bfs(pos);
    for(int i = 1;i<=n;++i)
        dis2[i] = dis[i];
    c = 0;
    for(int i =1;i<=n;++i)
    {
        if(dis1[i]+dis2[i]>dis1[c]+dis2[c]&&i!=a&&i!=b) c =i;
    }
    int ans = (dis1[b]+dis2[c]+dis1[c])/2;
    cout << ans <<endl;
    cout  << a << " "<< b << " " <<c;

    return 0;
}

 

posted @ 2020-02-09 11:12  浅花迷人  阅读(146)  评论(0编辑  收藏  举报