Educational Codeforces Round 108 [Rated for Div. 2](前三题)

A.Red and Blue Beans
You have r red and b blue beans. You’d like to distribute them among several (maybe, one) packets in such a way that each packet:
has at least one red bean (or the number of red beans ri≥1);
has at least one blue bean (or the number of blue beans bi≥1);
the number of red and blue beans should differ in no more than d (or |ri−bi|≤d)
Can you distribute all beans?
Input
The first line contains the single integer t (1≤t≤1000) — the number of test cases.

The first and only line of each test case contains three integers r, b, and d (1≤r,b≤109; 0≤d≤109) — the number of red and blue beans and the maximum absolute difference in each packet.

Output
For each test case, if you can distribute all beans, print YES. Otherwise, print NO.

You may print every letter in any case you want (so, for example, the strings yEs, yes, Yes and YES are all recognized as positive answer).

Example
inputCopy
4
1 1 0
2 7 3
6 1 4
5 4 0
outputCopy
YES
YES
NO
NO
Note
In the first test case, you can form one packet with 1 red and 1 blue bean. The absolute difference |1−1|=0≤d.

In the second test case, you can form two packets: 1 red and 4 blue beans in the first packet and 1 red and 3 blue beans in the second one.

In the third test case, since b=1, you can form only one packet with 6 red and 1 blue beans. The absolute difference |6−1|=5>d.

In the fourth test case, since d=0 so each packet should contain the same number of red and blue beans, but r≠b.
题意:你有r个红豆b个蓝豆,给你一个d,问你能不能把这些恰好豆子分在很多个口袋,对于每个口袋要求为:两种豆子至少各有一个、两种豆子数量差值绝对值小于等于d
总数少的那种豆子每个口袋尽量只放一个,假设放了n个口袋,然后把总数多的豆子平均放在这n个口袋里,最后看差值最大的那组有没有大于d
代码:

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 50;
#define reset(x) memset(x, 0, sizeof(x))
#define Q_in_out ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
typedef long long int ll;
typedef long double ld;
typedef pair<int, int> P;
int solve()
{
    int r,b,d;
    cin>>r>>b>>d;
    if(r==b){
        cout<<"YES"<<endl;
        return 0;
    }
    if(ceil(double((max(r,b)-min(r,b)))/double(min(r,b)))>d){
        cout<<"NO"<<endl;
    }
    else
    {
        cout<<"YES"<<endl;
    }
    
    return 0;
}
int main()
{
    Q_in_out 
    int t;
    cin >> t;
    // t=1;
    while (t--)
    {
        solve();
    }
    return 0;
}

B. The Cake Is a Lie
There is a n×m grid. You are standing at cell (1,1) and your goal is to finish at cell (n,m).

You can move to the neighboring cells to the right or down. In other words, suppose you are standing at cell (x,y). You can:

move right to the cell (x,y+1) — it costs x burles;
move down to the cell (x+1,y) — it costs y burles.
Can you reach cell (n,m) spending exactly k burles?

Input
The first line contains the single integer t (1≤t≤100) — the number of test cases.

The first and only line of each test case contains three integers n, m, and k (1≤n,m≤100; 0≤k≤104) — the sizes of grid and the exact amount of money you need to spend.

Output
For each test case, if you can reach cell (n,m) spending exactly k burles, print YES. Otherwise, print NO.

You may print every letter in any case you want (so, for example, the strings yEs, yes, Yes and YES are all recognized as positive answer).

Example
inputCopy
6
1 1 0
2 2 2
2 2 3
2 2 4
1 4 3
100 100 10000
outputCopy
YES
NO
YES
NO
YES
NO
Note
In the first test case, you are already in the final cell, so you spend 0 burles.

In the second, third and fourth test cases, there are two paths from (1,1) to (2,2): (1,1) → (1,2) → (2,2) or (1,1) → (2,1) → (2,2). Both costs 1+2=3 burles, so it’s the only amount of money you can spend.

In the fifth test case, there is the only way from (1,1) to (1,4) and it costs 1+1+1=3 burles.
题意:每次移动一步向下或者向右,问,从(1,1)到(n,m),经验证,所有方案最终总burles大小都一样…即(m-1)*n+n-1
代码:

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 50;
#define reset(x) memset(x, 0, sizeof(x))
#define Q_in_out ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
typedef long long int ll;
typedef long double ld;
typedef pair<int, int> P;
int solve()
{
    int n,m,k;
    cin>>n>>m>>k;
    if((m-1)*n+n-1==k) cout<<"YES";
    else cout<<"NO";
    
    return 0;
}
int main()
{
    Q_in_out 
    int t;
    cin >> t;
    // t=1;
    while (t--)
    {
        solve();
        cout<<endl;
    }
    return 0;
}

C. Berland Regional
Polycarp is an organizer of a Berland ICPC regional event. There are n universities in Berland numbered from 1 to n. Polycarp knows all competitive programmers in the region. There are n students: the i-th student is enrolled at a university ui and has a programming skill si.

Polycarp has to decide on the rules now. In particular, the number of members in the team.

Polycarp knows that if he chooses the size of the team to be some integer k, each university will send their k strongest (with the highest programming skill s) students in the first team, the next k strongest students in the second team and so on. If there are fewer than k students left, then the team can’t be formed. Note that there might be universities that send zero teams.

The strength of the region is the total skill of the members of all present teams. If there are no teams present, then the strength is 0.

Help Polycarp to find the strength of the region for each choice of k from 1 to n.

Input
The first line contains a single integer t (1≤t≤1000) — the number of testcases.

The first line of each testcase contains a single integer n (1≤n≤2⋅105) — the number of universities and the number of students.

The second line of each testcase contains n integers u1,u2,…,un (1≤ui≤n) — the university the i-th student is enrolled at.

The third line of each testcase contains n integers s1,s2,…,sn (1≤si≤109) — the programming skill of the i-th student.

The sum of n over all testcases doesn’t exceed 2⋅105.

Output
For each testcase print n integers: the strength of the region — the total skill of the members of the present teams — for each choice of team size k.

Example
inputCopy
4
7
1 2 1 2 1 2 1
6 8 3 1 5 1 5
10
1 1 1 2 2 2 2 3 3 3
3435 3014 2241 2233 2893 2102 2286 2175 1961 2567
6
3 3 3 3 3 3
5 9 6 7 9 7
1
1
3083
outputCopy
29 28 26 19 0 0 0
24907 20705 22805 9514 0 0 0 0 0 0
43 43 43 32 38 43
3083
Note
In the first testcase the teams from each university for each k are:

k=1:
university 1: [6],[5],[5],[3];
university 2: [8],[1],[1];
k=2:
university 1: [6,5],[5,3];
university 2: [8,1];
k=3:
university 1: [6,5,5];
university 2: [8,1,1];
k=4:
university 1: [6,5,5,3];
题意:输入n,然后输入n个学生(1n),第i个的值代表这个学生归属于大学i,n个skill,列举k从1n的情况下技能总和(k代表每个学校每支队伍队员数,当学校队员数小于k时skill总和为0)。
…看不懂题意的话看看样例一吧,头疼表达不出来…
思路:skill降序排序,这样就能保证派出的队员skill最大,再将前缀数组求出,这样就能查表知道x个队员上场时的总skill(总结的还是有点乱)
代码:(ps:此代码被hack了)

#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 50;
#define reset(x) memset(x, 0, sizeof(x))
#define Q_in_out ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
typedef long long int ll;
typedef long double ld;
typedef pair<int, int> P;
ll a[N],b[N];
int solve()
{
    int n;
    cin>>n;
    reset(a);
    reset(b);
    for(int i=0;i<n;i++)
        cin>>a[i];
    for(int i=0;i<n;i++)
        cin>>b[i];
    map<ll,vector<ll> >all;
    map<ll,vector<ll> >tab;
    for(int i=0;i<n;i++){
        all[a[i]].push_back(b[i]);
        tab[a[i]].push_back(b[i]);
    }
    int maxt=-1;
    for(map<ll,vector<ll> >::iterator it=tab.begin();it!=tab.end();it++){
    	sort(it->second.rbegin(),it->second.rend());
    	for(int i=1;i<it->second.size();i++)
        {
            it->second[i]+=it->second[i-1];
        }
	}
    for(map<ll,vector<ll> >::iterator it=all.begin();it!=all.end();it++){
        sort(it->second.rbegin(),it->second.rend());
        int sie=it->second.size();
        if(sie>maxt) maxt=sie;
        ll tmp=0;
    }
    for(int i=1;i<=n;i++){
        if(i>maxt){
            cout<<0<<' ';
            continue;
        }
        ll tmp=0;
        if(i==1){
            for(map<ll,vector<ll> >::iterator it=all.begin();it!=all.end();it++){
				tmp+=tab[it->first][tab[it->first].size()-1];
            }
            cout<<tmp<<' ';
            continue;
        }
        for(map<ll,vector<ll> >::iterator it=all.begin();it!=all.end();it++){
            int sie=it->second.size();
            if(i>sie) continue;
            if(sie%i==0)      //正好能分完
            {
                tmp+=tab[it->first][tab[it->first].size()-1];
                continue;
            }
            int len=sie%i;	//有len个队员 不能上场
            int key=sie-1-len;
            tmp+=tab[it->first][key];
        }
        cout<<tmp<<' ';
    }
    return 0;
}
int main()
{
    Q_in_out 
    int t;
    cin >> t;
    // t=1;
    while (t--)
    {
        solve();
        cout<<endl;
    }
    return 0;
}

更正,C题被hack(tle)掉了,以下代码为改正后AC的代码(先把结果算完后保存在数组里):

#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 50;
#define reset(x) memset(x, 0, sizeof(x))
#define Q_in_out ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
typedef long long int ll;
typedef long double ld;
typedef pair<int, int> P;
ll a[N],b[N];
int solve()
{
    int n;
    cin>>n;
    reset(a);
    reset(b);
    for(int i=0;i<n;i++)
        cin>>a[i];
    for(int i=0;i<n;i++)
        cin>>b[i];
    map<ll,vector<ll> >all;
    for(int i=0;i<n;i++)
        all[a[i]].push_back(b[i]);

    vector<ll>res(n+1,0);
    for(map<ll,vector<ll> >::iterator it=all.begin();it!=all.end();it++){
    	sort(it->second.begin(),it->second.end());
        int sz=it->second.size();
    	for(int i=1;i<sz;i++)
        {
            it->second[i]+=it->second[i-1];
        }
        for(int i=1;i<=sz;i++){
            if(sz%i){
                res[i]+=it->second[sz-1]-it->second[(sz%i)-1];
            }
            else
            {
                res[i]+=it->second[sz-1];
            }
        }
	}
    
    for(int k=1;k<=n;k++){
        cout<<res[k]<<' ';
    }
    return 0;
}
int main()
{
    Q_in_out 
    int t;
    cin >> t;
    // t=1;
    while (t--)
    {
        solve();
        cout<<endl;
    }
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值