码迷,mamicode.com
首页 > 其他好文 > 详细

Codeforces 817+818(A~C)

时间:2019-08-15 01:09:45      阅读:149      评论:0      收藏:0      [点我收藏+]

标签:cli   return   perm   mod   get   必须   ==   eve   多少   

(点击题目即可查看原题)

817A Treasure Hunt

题意:给出起点和终点,每次移动只能从 (a,b)移动至(a+x,b+y) , (a+x,b-y) , (a-x,b+y) , (a-x,b-y) 四个位置,问能否从终点走到起点

思路:先计算出起点和终点的横纵坐标之差 X,Y, 首先必须满足 X%x == 0 && Y % y == 0 ,这样才可以走到和终点一样的位置,后计算 X/x . Y/y ,我们注意到如果 X/x != Y/y 那么就可能无法用到达,不过,我们可以在两次运动过程中只走X方向或者Y方向,也就是如果 abs( X/x - Y/y ) % 2 == 0 ,那么也是可以到达的;此外的情况都是无法到达的。

技术图片
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<string>
#include<fstream>
#include<vector>
#include<stack>
#include <map>
#include <iomanip>
#define bug cout << "**********" << endl
#define show(x,y) cout<<"["<<x<<","<<y<<"] "
//#define LOCAL = 1;
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const ll mod = 1e6 + 3;
const int Max = 1e5 + 10;

int s_x, s_y, e_x, e_y;
int x, y;

int main()
{
#ifdef LOCAL
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
    while (scanf("%d%d%d%d", &s_x, &s_y, &e_x, &e_y) != EOF)
    {
        scanf("%d%d", &x, &y);
        if (abs(s_x - e_x) % x == 0 && abs(s_y - e_y) % y == 0
         && abs(abs(s_x - e_x) / x - abs(s_y - e_y) / y) % 2 == 0)
        {
            printf("YES\n");
        }
        else
        {
            printf("NO\n");
        }
    }
    return 0;
}
817A

 817B Makes And The Product 

题意:给出n个数a[1] ~ a[n] ,求使得 a[i] * a[j] * a[k] 最小的组合 (i,j,k) 有多少个,其中 i , j , k 互不相等。

思路:摆明了让你求最小的三个值的个数,求出最小值,,次小值的,,第三小值的个数,然后根据以下规律凑成组合并输出个数,emmm,组合数

1)最小的有三个以上,那么三个均有最小的组成

2)如果最小的只有两个,那么最小的肯定要选,所以由两个最小和一个次小组成

3)最小的只有一个,次小的有两个以上,那么由一个最小和两个次小组成

4)最小和次小都只有一个,那么由最小,次小,第三小各选一个组成

输出对应的组合数即可(博主用自己的组合数板子写了第一发,结果范围不够,WA了,不过这个地方不需要用组合数板子来写,因为计算次数最多4次,直接算就好)

技术图片
#include<iostream>
#include<cstdio>
#include<stdio.h>
#include<algorithm>
#include<cstring>
#include<queue>
#include<string>
#include<fstream>
#include<vector>
#include<stack>
#include <map>
#include <iomanip>
#define bug cout << "**********" << endl
#define show(x,y) cout<<"["<<x<<","<<y<<"] "
//#define LOCAL = 1;
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const ll mod = 1e9 + 7;
const int Max = 1e5 + 10;

int n;
int a[Max];
map<int, int>mp;    //记录每个数字出现的次数


int main()
{
#ifdef LOCAL
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
    while (scanf("%d", &n) != EOF)
    {
        mp.clear();
        for (int i = 1;i <= n;i++)
        {
            scanf("%d", a + i), mp[a[i]]++;
        }

        sort(a + 1, a + 1 + n);
        int tot = unique(a + 1, a + 1 + n) - a - 1; //排序并去重,使得a[1]~a[3]对应最小的三个数

        if (mp[a[1]] >= 3)                                    //最小的有三个以上,那么三个均有最小的组成
        {
            printf("%d\n",mp[a[1]] * (mp[a[1]] -1 ) * (mp[a[1]] -2) / 6);
        }
        else if (mp[a[1]] == 2)                               //如果最小的只有两个,那么最小的肯定要选,所有由两个最小和一个次小组成
        {
            printf("%d\n", mp[a[2]]);
        }
        else if (mp[a[1]] == 1 && mp[a[2]] >= 2)              //最小的只有一个,次小的有两个以上,那么有一个最小和两个次小组成
        {
            printf("%d\n", mp[a[2]] * (mp[a[2]]  - 1) / 2);
        }
        else                                                  //最小和次小都只有一个,那么最小,次小,第三小各选一个
        {
            printf("%d\n",mp[a[3]]);
        }
    }

    return 0;
}
817B

817C Really Big Numbers

题意:给出两个数n,s,问在 [1,n] 范围内有多少个数  满足 x 和 x 的各个位上的数之和 大于s ( x 属于 [1,n])

思路:打表找规律,发现从某一个数开始,后面的数都是满足条件的,那么就简单了,二分第一个满足的数,其后的数就都满足条件了

技术图片
#include<iostream>
#include<cstdio>
#include<stdio.h>
#include<algorithm>
#include<cstring>
#include<queue>
#include<string>
#include<fstream>
#include<vector>
#include<stack>
#include <map>
#include <iomanip>

#define bug cout << "**********" << endl
#define show(x, y) cout<<"["<<x<<","<<y<<"] "
#define LOCAL = 1;
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const ll mod = 1e9 + 7;
const int Max = 1e5 + 10;

ll n, m;

int main()
{
#ifdef LOCAL
    //freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
#endif
    while (scanf("%lld%lld", &n, &m) != EOF)
    {
        ll l = 1, r = n;
        while (l <= r)
        {
            ll sum = 0;
            ll mid = (l + r) >> 1;
            ll k = mid;
            while (k)
            {
                sum += k % 10;
                k /= 10;
            }
            if (abs(mid - sum) < m)
            {
                l = mid + 1;
            }
            else
            {
                r = mid - 1;
            }
        }
        printf("%lld\n", n - l + 1);
    }
    return 0;
}
817C

818A Diplomas and Certificates 

题意:有n个人,需要为他们分两种奖品,其中一种奖品的数量必须是另一种奖品数量的k倍,每个人只能分到一个奖品,并且有奖品的人数不得超过n/2个,输出两种奖品的数量和没有得奖的人数

思路:一个简单的公式 x + k * x <= n/2 ,得到的x向下取整,输出 x , k * x , n - (k+1)*x 就OK了。

技术图片
#include<iostream>
#include<cstdio>
#include<stdio.h>
#include<algorithm>
#include<cstring>
#include<queue>
#include<string>
#include<fstream>
#include<vector>
#include<stack>
#include <map>
#include <iomanip>
#define bug cout << "**********" << endl
#define show(x,y) cout<<"["<<x<<","<<y<<"] "
//#define LOCAL = 1;
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const ll mod = 1e9 + 7;
const int Max = 1e5 + 10;

ll n, k;

int main()
{
#ifdef LOCAL
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
    while (scanf("%lld%lld", &n, &k) != EOF)
    {
        ll x = (n/2) / (k + 1);
        printf("%lld %lld %lld\n", x, k*x, n - (k + 1)*x);
    }
    return 0;
}
818A

818B Permutation Game 

题意:有n个人围成环玩游戏,每个人的位置按顺时针从1~n排列,一共m轮,每轮选出一个领导者,用l[i]表示第i轮的领导是谁,每个人当领导的时候,他会选择他后面第a[i]个人担任下一轮的领导,并且a[i] 只能是 1 ~ n 中的值,并且每个人的a[i]  都不一样,换句话说,n个人的a[i]组成 1 ~ n ,给出了n,m, l[i],求a[i],如果不存在,输出-1

思路:我们注意到,每一轮的领导者都是上一轮领导后的第a[i]位,那么 a[i-1] = l[i] - l[i-1] ,又因为n个人排成环,所以当 l[i] < l[i-1] 的时候,a[i-1] = l[i] + n - l[i-1],这样就可以求出a[i]了,对于不确定的a[i],我们给其一个没有出现过的数当成这个数的a[i]即可。而如果某两个人的a[i]相同,那么就不存在,输出-1

技术图片
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<string>
#include<fstream>
#include<vector>
#include<stack>
#include <map>
#include <iomanip>

#define bug cout << "**********" << endl
#define show(x, y) cout<<"["<<x<<","<<y<<"] "
#define LOCAL = 1;
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const ll mod = 1e9 + 7;
const int Max = 1e5 + 10;

int n, m;
int leader[Max];            //记录第i个领导者的位置
int a[Max];                 //每次移动距离
int vis[Max];

int main()
{
#ifdef LOCAL
    //freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
#endif
    while (scanf("%d%d", &n, &m) != EOF)
    {
        memset(a, -1, sizeof(a));
        memset(vis, 0, sizeof(vis));
        bool ok = true;

        scanf("%d", leader + 1);
        for (int i = 2; i <= m; i++)
        {
            scanf("%d", leader + i);
            int temp = 0;
            int add = 0;
            if(leader[i] <= leader[i-1])
            {
                add += n;
            }
            temp = leader[i] + add - leader[i-1];

            if (a[leader[i - 1]] == -1 || a[leader[i - 1]] == temp) //同一个人同一个a[i]没有问题
            {
                if (vis[temp] && a[leader[i - 1]] == -1)            //不同的人有相同的a[i]
                {
                    ok = false;
                }
                else
                {
                    a[leader[i - 1]] = temp;
                    vis[temp] = true;
                }
            }
            else
            {
                ok = false;
            }
        }

        if (!ok)
        {
            printf("-1\n");
        }
        else
        {
            for (int i = 1; i <= n; i++)
            {
                if (a[i] != -1)
                {
                    printf("%d ", a[i]);
                }
                else
                {
                    for (int j = 1; j <= n; j++)
                    {
                        if (!vis[j])
                        {
                            printf("%d ", j);
                            vis[j] = true;
                            break;
                        }
                    }
                }
            }
            printf("\n");
        }
    }
    return 0;
}
818B

818C Sofa Thief 

题意:在一个 n * m 的房间内,有 d 个沙发,每个沙发占两个单位面积,我们将(x,y)视作一单位面积,给出每个沙发的位置x1,y1,x2,y2 ,代表这个沙发的位置为 (x1,y1),(x2,y2),保证没有两个及以上的沙发占用同一个位置,最后给出我们需要的沙发的信息cntL,cntR,cntB,cnrT,分别代表我们需要找的沙发的 左边沙发的个数,右边沙发的个数,底部沙发的个数,顶部沙发的个数,注意,只要两个沙发A,B,满足 A.x < B.x ,x = x1,x2,那么A就在B的左边,如果 A.y < B.y ,y = y1,y2,那么A在B的顶部,也就是说,y值大的在底部,问满足这个要求的沙发的编号,如果不存在,输出-1

思路:思路很简单,不过很多细节需要注意,具体方法如下

  当前沙发左边的沙发数:所有左边界小于当前沙发右边界的沙发总数,
  1、如果找到第一个大于等于当前沙发右边界的,
    1) 如果当前沙发左右边界相等,那么此前的都是

    2)如果不相等,减去自身;
  2、如果没有大于等于当前沙发右边界的,那么此前所有的沙发都是的

  当前沙发右边的沙发数:所有右边界大于当前沙发左边界的沙发总数,
  1、如果找到第一个大于当前沙发左边界的,
    1)如果当前沙发左右边界相等,那么此后的都是

    2)如果不相等,减去自身
  2、如果没有找到大于当前沙发左边界的,那么就没有

  当前沙发底部的沙发数:所有上边界大于当前沙发下边界的沙发总数
  1、找到第一个大于当前沙发下边界的沙发,
    1) 如果上下边界相同,那么此后的都是

    2)如果不相等,减去自身
  2、如果没有大于当前沙发下边界的沙发,那么就没有

  当前沙发顶部的沙发数:所有下边界小于当前沙发上边界的沙发总数
  1、如果找到第一个大于等于当前沙发上边界的沙发
    1) 如果上下边界相同,那么此前的都是

    2)如果不相等,那么减去自身
  2、如果没有大于等于当前沙发上边界的沙发,那么全都是

技术图片
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#include<string>
#include<fstream>
#include<vector>
#include<stack>
#include <map>
#include <iomanip>

#define bug cout << "**********" << endl
#define show(x, y) cout<<"["<<x<<","<<y<<"] "
#define LOCAL = 1;
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const ll mod = 1e9 + 7;
const int Max = 1e5 + 10;

struct Node
{
    int x1, y1, x2, y2;
} node[Max];


int d, n, m;
int cntL, cntR, cntT, cntB;
int R[Max], L[Max], T[Max], B[Max];        //记录四个边界


int main()
{
#ifdef LOCAL
    //freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
#endif
    while (scanf("%d%d%d", &d, &n, &m) != EOF)
    {
        for (int i = 1; i <= d; i++)
        {
            scanf("%d%d%d%d", &node[i].x1, &node[i].y1, &node[i].x2, &node[i].y2);
            if (node[i].x1 > node[i].x2)
                swap(node[i].x1, node[i].x2);
            if (node[i].y1 > node[i].y2)        //大数为底部
                swap(node[i].y1, node[i].y2);
             
            L[i] = node[i].x1;                  //记录每个沙发的左边界
            R[i] = node[i].x2;                  //记录每个沙发的右边界
            B[i] = node[i].y1;                  //记录每个沙发的下边界
            T[i] = node[i].y2;                  //记录每个沙发的上边界,值大的为上边界
            //cout << "L: " << L[i] << " R: " << R[i] << " B: " << B[i] << " T: " << T[i] << endl;
        }
        scanf("%d%d%d%d", &cntL, &cntR, &cntT, &cntB);
         
        sort(R + 1, R + 1 + d);
        sort(L + 1, L + 1 + d);
        sort(B + 1, B + 1 + d);
        sort(T + 1, T + 1 + d);       //均升序排序
         
        int id = -1;
        for (int i = 1; i <= d; i++)            //枚举沙发
        {
            int ansL = lower_bound(L + 1, L + 1 + d, node[i].x2) - L;
            if (ansL == d + 1)                  //没有找到大于等于当前沙发右边界的沙发
            {
                ansL = d - 1;
            }
            else
            {
                ansL--;
                if (node[i].x1 != node[i].x2)    //排除自身左边界的影响
                {
                    ansL--;
                }
            }
            //cout <<"ansL: "<<ansL<<endl;
            if (ansL != cntL)
                continue;
            /**********************************************/
            int ansR = upper_bound(R + 1, R + 1 + d, node[i].x1) - R;
            if (ansR == d + 1)                  //没有找到大于当前沙发左边界的沙发,那么都是
            {
                ansR = 0;
            }
            else
            {
                ansR = d - ansR + 1;
                if (node[i].x1 != node[i].x2)    //排除自身右边界的影响
                {
                    ansR--;
                }
            }
            //cout <<"ansR: "<<ansR<<endl;
            if (ansR != cntR)
                continue;
            /**********************************************/
            int ansB = upper_bound(T + 1, T + 1 + d, node[i].y1) - T;
            if (ansB == d + 1)                    //没有找到大于当前沙发下边界的沙发,那么没有
            {
                ansB = 0;
            }
            else
            {
                ansB = d - ansB + 1;
                if (node[i].y1 != node[i].y2)
                {
                    ansB--;
                }
            }
            //cout <<"ansB: "<<ansB<<endl;
            if (ansB != cntB)
                continue;
            /**********************************************/
            int ansT = lower_bound(B + 1, B + 1 + d, node[i].y2) - B;
            if (ansT == d + 1)
            {
                ansT = d - 1;
            }
            else
            {
                ansT--;
                if (node[i].y1 != node[i].y2)
                {
                    ansT--;
                }
            }
            //cout <<"ansT: "<<ansT<<endl;
            if (ansT != cntT)
                continue;
            /**********************************************/
            id = i;
            break;
        }
        printf("%d\n", id);
    }
    return 0;
}

//当前沙发左边的沙发数:所有左边界小于当前沙发右边界的沙发总数,
//1、如果找到第一个大于等于当前沙发右边界的,
//1) 如果当前沙发左右边界相等,那么此前的都是,2)如果不相等,减去自身;
//2、如果没有大于等于当前沙发右边界的,那么此前所有的沙发都是的

//当前沙发右边的沙发数:所有右边界大于当前沙发左边界的沙发总数,
//1、如果找到第一个大于当前沙发左边界的,
//1)如果当前沙发左右边界相等,那么此后的都是,2)如果不相等,减去自身
//2、如果没有找到大于当前沙发左边界的,那么就没有

//当前沙发底部的沙发数:所有上边界大于当前沙发下边界的沙发总数
//1、找到第一个大于当前沙发下边界的沙发,
//1) 如果上下边界相同,那么此后的都是,2)如果不相等,减去自身
//2、如果没有大于当前沙发下边界的沙发,那么就没有

//当前沙发顶部的沙发数:所有下边界小于当前沙发上边界的沙发总数
//1、如果找到第一个大于等于当前沙发上边界的沙发
//1) 如果上下边界相同,那么此前的都是,2)如果不相等,那么减去自身
//2、如果没有大于等于当前沙发上边界的沙发,那么全都是
818C

Codeforces 817+818(A~C)

标签:cli   return   perm   mod   get   必须   ==   eve   多少   

原文地址:https://www.cnblogs.com/winter-bamboo/p/11355591.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!