Codeforces Round 680 Div2 解题记录

Array Rearrangment

Array Rearrangment

You are given two arrays a a a and b b b, each consisting of n n n positive integers, and an integer x x x. Please determine if one can rearrange the elements of b so that a i + b i a_i+b_i ai+bi x x x holds for each i i i (1≤ i i i n n n).
Input
The first line of input contains one integer t (1≤ t t t≤100) — the number of test cases. t t t blocks follow, each describing an individual test case.
The first line of each test case contains two integers n n n and x x x (1≤ n n n≤50; 1≤ x x x≤1000) — the length of arrays a and b, and the parameter x x x, described in the problem statement.
The second line of each test case contains n n n integers a 1 a_1 a1, a 2 a_2 a2,…, a n a_n an (1≤ a 1 a_1 a1 a 2 a_2 a2≤⋯≤ a n a_n an x x x) — the elements of array a in non-descending order.
The third line of each test case contains n integers b 1 b_1 b1, b 2 b_2 b2,…, b n b_n bn (1≤ b 1 b_1 b1 b 2 b_2 b2≤⋯≤ b n b_n bn x x x) — the elements of array b in non-descending order.
Test cases are separated by a blank line.
Output
For each test case print Yes if one can rearrange the corresponding array b so that a i + b i a_i+b_i ai+bi x x x holds for each i i i (1≤i≤n) or No otherwise.
Each character can be printed in any case.

Input Example

4
3 4
1 2 3
1 1 2

2 6
1 4
2 5

4 4
1 2 3 4
1 2 3 4

1 5
5
5

Output Example

Yes
Yes
No
No

两个数组 a a a b b b,问重排列后 a [ i ] a[i] a[i] + b [ i ] b[i] b[i] <= x x x (1 ≤ \leq i i i ≤ \leq n n n)
输入一个 t t t,表示有 t t t 组测试,给出一个 n n n x x x , n n n 表示数组长度, x x x 如题所述。如果所有的 a [ i ] a[i] a[i] + b [ i ] b[i] b[i] ≤ \leq x x x 输出 y e s yes yes,否则输出 N o No No

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e3 + 7;
int a[maxn],b[maxn];
int main()
{
    
    
    int t;
    cin>>t;
    while(t--)
    {
    
    
        int n, x;
        cin>>n>>x;
        for(int i = 0; i < n; i++) cin>>a[i];
        for(int i = 0; i < n; i++) cin>>b[i];
        sort(a,a+n);
        sort(b,b+n);
        reverse(a,a+n);
 
        bool ok = false;
        for(int i = 0; i < n; i++)
            if(a[i] + b[i] > x) ok = true;
 
        if(ok) cout<<"No"<<'\n';
        else cout<<"Yes"<<'\n';
    }
    return 0;
}

Elimination

Elimination

There is a famous olympiad, which has more than a hundred participants. The Olympiad consists of two stages: the elimination stage, and the final stage. At least a hundred participants will advance to the final stage. The elimination stage in turn consists of two contests.

A result of the elimination stage is the total score in two contests, but, unfortunately, the jury lost the final standings and has only standings for the first and for the second contest separately.

In each contest, the participants are ranked by their point score in non-increasing order. When two participants have a tie (earned the same score), they are ranked by their passport number (in accordance with local regulations, all passport numbers are distinct).

In the first contest, the participant on the 100-th place scored a a a points. Also, the jury checked all participants from the 1-st to the 100-th place (inclusive) in the first contest and found out that all of them have at least b b b points in the second contest.

Similarly, for the second contest, the participant on the 100-th place has c c c points. And the jury checked that all the participants from the 1-st to the 100-th place (inclusive) have at least d d d points in the first contest.

After two contests, all participants are ranked by their total score in two contests in non-increasing order. When participants have the same total score, tie-breaking with passport numbers is used. The cutoff score to qualify to the final stage is the total score of the participant on the 100-th place.

Given integers a a a, b b b, c c c, d d d, please help the jury determine the smallest possible value of the cutoff score.

Input
You need to process t t t test cases.

The first line contains an integer t t t (1≤ t t t≤3025) — the number of test cases. Then descriptions of t test cases follow.

The first line of each test case contains four integers a a a, b b b, c c c, d d d (0 ≤ a , b , c , d a,b,c,d a,b,c,d ≤ 9; d d d a a a; b b b c c c).

One can show that for any test case satisfying the constraints above, there is at least one olympiad scenario possible.

Output
For each test case print a single integer — the smallest possible cutoff score in some olympiad scenario satisfying the given information.

Input Example

2
1 2 2 1
4 8 9 2

Output Example

3
12

Note
For the first test case, consider the following olympiad scenario: there are 101 participants in the elimination stage, each having 1 point for the first contest and 2 points for the second contest. Hence the total score of the participant on the 100-th place is 3.

For the second test case, consider the following olympiad scenario:

there are 50 participants with points 5 and 9 for the first and second contest respectively;
50 participants with points 4 and 8 for the first and second contest respectively;
and 50 participants with points 2 and 9 for the first and second contest respectively.
Hence the total point score of the participant on the 100-th place is 12.
进行两次比赛,每次比赛排名非递增顺序。
第一场第 100 名选手得 a a a 分,第二场每个选手最少得 b b b
第二场第 100 名选手得 b b b 分,第一场每个选手至少得 d d d
给你整数 a a a, b b b, c c c, d d d 问第 100 名选手至少总分多少?
输入一个 t t t 代表至少有 t t t 组测试
每组测试输入四个数 a a a, b b b, c c c, d d d
每组测试输出一个整数,代表第 100 名最少总分多少。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main()
{
    
    
    int t;
    cin>>t;
    while(t--)
    {
    
    
        int a,b,c,d;
        cin>>a>>b>>c>>d;
        cout<<max(a+b,c+d)<<endl;
    }
    return 0;
}

Division

Division

Oleg’s favorite subjects are History and Math, and his favorite branch of mathematics is division.

To improve his division skills, Oleg came up with t t t pairs of integers p i p_i pi and q i q_i qi and for each pair decided to find the greatest integer x i x_i xi, such that:

p i p_i pi is divisible by x i x_i xi;
x i x_i xi is not divisible by q i q_i qi.
Oleg is really good at division and managed to find all the answers quickly, how about you?

Input
The first line contains an integer t t t (1≤ t t t ≤50) — the number of pairs.

Each of the following t t t lines contains two integers p i p_i pi and q i q_i qi (1≤ p i p_i pi 1 0 18 10^{18} 1018; 2≤ q i q_i qi 1 0 9 10^9 109) — the i-th pair of integers.
Output
Print t integers: the i-th integer is the largest x i x_i xi such that p i p_i pi is divisible by x i x_i xi, but x i x_i xi is not divisible by q i q_i qi.

One can show that there is always at least one value of x i x_i xi satisfying the divisibility conditions for the given constraints.

Input Example

3
10 4
12 6
179 822

Output Example

10
4
179

Note
For the first pair, where p 1 p_1 p1 = 10 and q 1 q_1 q1 = 4, the answer is x 1 x_1 x1 = 10, since it is the greatest divisor of 10 and 10 is not divisible by 4.

For the second pair, where p 2 p_2 p2 = 12 and q 2 q_2 q2 = 6, note that

12 is not a valid x 2 x_2 x2, since 12 is divisible by q 2 q_2 q2 = 6;6 is not valid x 2 x_2 x2 as well: 6 is also divisible by q 2 q_2 q2 = 6.
The next available divisor of p 2 p_2 p2 = 12 is 4, which is the answer, since 4 is not divisible by 6.

三个数 p p p, x x x, q q q
p p p% x x x == 0
x x x% q q q != 0
输入一个 t t t,代表有 t t t 组测试
每组测试输入一个 p p p, q q q
每组测试答案占一行,输出满足题意的 x x x 的最大值

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 998244353, maxn = 3e5 + 7;
int a[maxn];
int main()
{
    
    
    int t;
    scanf(" %d",&t);
    while(t--)
    {
    
    
        ll x,y;
        cin>>x>>y;
        if(x%y) cout<<x<<'\n';
        else
        {
    
    
            vector<ll>factor;
            factor.clear();
            ll r = y;
            ll sy = sqrt(r);
            for(int i = 2; i <= sy; ++i)
            {
    
    
                if(r%i == 0)
                {
    
    
                    factor.push_back(i);
                    while(r%i == 0) r /= i;
                }
            }
            if(r != 1) factor.push_back(r);
 
            vector<ll>ans;
            ans.clear();
            int len = factor.size();
            for(int i = 0; i < len; ++i)
            {
    
    
                ll op = x;
                while(op%y == 0) op /= factor[i];
                ans.push_back(op);
            }
            ll answer = -0x3f3f3f3f;
            for(int i = 0; i < ans.size(); ++i)
                answer = max(answer,ans[i]);
            cout<<answer<<endl;
        }
    }
    return 0;
}

Divide and Sum

Divide and Sum
在这里插入图片描述
在这里插入图片描述
给一个长度为 2 n 2n 2n 的数组,考虑数组 a a a 的子序列 p p p, q q q, s o r t sort sort p p p, q q q p p p 非递减 q q q 非递增,每个子序列长度为 n n n,数组中的元素不在子序列 p p p 就在子序列 q q q,对于每个子序列 f ( p , q ) f(p,q) f(p,q) = s u m sum sum(| x i x_i xi - y i y_i yi|)(1 ≤ \leq i i i ≤ \leq n)
s u m sum sum 取模,模数是 998244353 998244353 998244353
输入一个 n n n,第二行输入 2 n 2n 2n 个整数
输出取余数后的结果。


L u c a s Lucas Lucas定理求出 C 2 n n C^n_{2n} C2nn 的组合数,然后 s o r t sort sort一下数组,最后一个与第一个作差累计求和,前面后移,后面前移,取模后和和乘以取模后的组合数最后的答案取模。

#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int mod =  998244353, maxn = 3e5 + 7;
int s[maxn];
int qmi(int a, int k, int p)
{
    
    
    int res = 1;
    while (k)
    {
    
    
        if (k & 1) res = (ll)res * a % p;
        a = (ll)a * a % p;
        k >>= 1;
    }
    return res;
}

int C(int a, int b, int p)
{
    
    
    if (b > a) return 0;

    int res = 1;
    for (int i = 1, j = a; i <= b; i ++, j -- )
    {
    
    
        res = (ll)res * j % p;
        res = (ll)res * qmi(i, p - 2, p) % p;
    }
    return res;
}

int lucas(ll a, ll b, int p)
{
    
    
    if (a < p && b < p) return C(a, b, p);
    return (ll)C(a % p, b % p, p) * lucas(a / p, b / p, p) % p;
}

int main()
{
    
    
    int n;
    scanf("%d",&n);
    int len = n << 1;
    for(int i = 1; i <= len; ++i) scanf(" %d",&s[i]);
    ll a, b;
    a = len, b = n;
    int cnt = lucas(a, b, mod)%mod;
    sort(s+1,s+1+len);
    ll ans = 0;
    for(int i = 1, j = len; i < j; i++, j--) ans = (ans%mod+s[j] - s[i])%mod;
    cout<< cnt*(ans%mod)%mod<<'\n';
    return 0;
}

c f cf cf 官网 i d id id 看到的一个简短做法

#include<bits/stdc++.h>
#define M 998244353 
using namespace std;
long long n,a[300010],p[300010];
long long ans,sum;
int main()
{
    
    
    scanf("%lld",&n);p[1]=1,ans=n*2;
    for(int i=2;i<=n;i++)
        p[i]=p[M%i]*(M-M/i)%M,ans=ans*(n*2-i+1)%M*p[i]%M;
    for(int i=1;i<=n*2;i++) scanf("%lld",&a[i]);
    sort(a+1,a+n*2+1);
    for(int i=1;i<=n;i++)
        sum=(sum+a[n*2-i+1]-a[i])%M;
    printf("%lld",sum*ans%M);
	return 0;
}

Team-Building

Team-Building
在这里插入图片描述
在这里插入图片描述
n n n 个点,每个点有一种颜色,范围在 1 ~ k k k 之间, m m m 对关系,没对关系 x x x y y y 之间有一条边。有直接连接的边或者颜色一样的不能组队,问你有多少种组合?

直接贴的 c f cf cf i d id id上的,现场我肯定码不出来。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6+10;
struct Node{
    
    
    int u,v,fa,rk; bool ds;
    Node(int _u=0,int _v=0,int _fa=0,int _rk=0,bool _ds=0){
    
    
        u=_u; v=_v; fa=_fa; rk=_rk; ds=_ds;
    }
}st[N]; int top;
struct USF{
    
    
    int fa[N],rk[N],c; bool ds[N];
    void init(int n){
    
    
        for(int i=1;i<=n;++i){
    
    
            fa[i]=i; rk[i]=0; ds[i]=0;
        }
    }
    int unite(int u,int v){
    
    
        bool du=0,dv=0;
        //printf("uin\n");
        while(u!=fa[u]) du^=ds[u],u=fa[u];
        while(v!=fa[v]) dv^=ds[v],v=fa[v];
        //printf("uot\n");
        if(u==v) return du^dv;
        if(rk[u]<rk[v]){
    
    
            swap(u,v); swap(du,dv);
        }
        st[++top]=Node(u,v,fa[v],rk[u],ds[v]);
        fa[v]=u; ds[v]=du^dv^1;
        if(rk[u]==rk[v]) rk[u]++;
        return 2;
    }
    void undo(int t){
    
    
	    while(t--){
    
    
	        Node &o=st[top]; --top;
	        fa[o.v]=o.fa; ds[o.v]=o.ds;
	        rk[o.u]=o.rk;
	    }
	}
}usf;
int n,m,k,c[N];
struct Edge{
    
    
	int x,y;
	bool operator < (const Edge &r) const{
    
    
		if(c[x]!=c[r.x]) return c[x]<c[r.x];
		else return c[y]<c[r.y];
	}
	bool operator == (const Edge &r) const{
    
    
		return c[x]==c[r.x]&&c[y]==c[r.y];
	}
}e[N];
bool nt[N];
int main(){
    
    
	scanf("%d %d %d",&n,&m,&k); usf.init(n);
	for(int i=1;i<=n;++i) scanf("%d",&c[i]);
	for(int i=1;i<=m;++i){
    
    
		scanf("%d %d",&e[i].x,&e[i].y);
		if(c[e[i].x]==c[e[i].y]){
    
    
			if(!nt[c[e[i].x]]){
    
    
				if(usf.unite(e[i].x,e[i].y)==0){
    
    
					nt[c[e[i].x]]=true; --k;
				}
			}
			--i; --m;
		}else if(c[e[i].x]>c[e[i].y]){
    
    
			swap(e[i].x,e[i].y);
		}
	}
	sort(e+1,e+1+m);
	ll ans=1ll*k*(k-1)/2;
	for(int i=1,j=1;i<=m;i=j){
    
    
		int cnt=0,op,flg=nt[c[e[i].x]]|nt[c[e[i].y]];
		//if(!flg) printf("chk %d %d\n",c[e[i].x],c[e[i].y]);
		while(j<=m&&e[j]==e[i]){
    
    
			if(!flg){
    
    
				op=usf.unite(e[j].x,e[j].y);
				if(op==0){
    
    
					flg=1; --ans;
				}else if(op==2) ++cnt;
			}
			++j;
		}
		//if(flg) printf("not %d %d\n",c[e[i].x],c[e[i].y]);
		usf.undo(cnt);
	}
	printf("%lld\n",ans);
}

这场 c f cf cf 只会 A 、 B 、 C 、 D A、B、C、D ABCD,准备写个题解也是这几天在学这个 E E E的做法,所以发出来比较迟,最近想法,不一定熬夜打 c f cf cf,但是一定要补题。

猜你喜欢

转载自blog.csdn.net/Edviv/article/details/109467245