2021第7届中国大学生程序设计竞赛CCPC广州站, 签到题4题

Posted 小哈里

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021第7届中国大学生程序设计竞赛CCPC广州站, 签到题4题相关的知识,希望对你有一定的参考价值。

文章目录

补题链接:https://codeforces.com/gym/103415

I.Pudding Store

I. Pudding Store
time limit per test2.0 s
memory limit per test512 megabytes
inputstandard input
outputstandard output
159 is a boy. He has a pudding store.

There are n different puddings numbered from 1 to n lined up in a row in the pudding store. (Note that the i-th pudding in the row may not be the pudding with the number i.) Now, n students numbered from 1 to n are coming to sample these puddings in a specific way. That is, for the i-th student, he will sample each one of the first i puddings in the row. Sampling the pudding numbered i gives the sampler a satisfaction value of 2×i. And if the sum of all satisfaction values that the i-th student gets is divisible by i, we would say that the i-th student is satisfied.

Now, 159 wants to know, how many different arrangements of the puddings in a row that every student will be satisfied after sampling. Two arrangements are different, if there exists a pudding that its position is different. Note that the number of arrangements may be very large so he just needs the remainder after division by 998244353 of the result.

Input
Each test contains multiple test cases. The first line contains the number of test cases t (1≤t≤10). Description of the test cases follows.

The first and only line of each test case contains one integer n (1≤n≤109) — the number of the puddings and the students.

Output
For each test case, print a single line that contains one integer — the number of satisfying arrangements modulo 998244353.

Example
inputCopy
3
1
2
3
outputCopy
1
2
6

题意:

  • 构造一个1-n的排列,需要满足前i项的和是2i的倍数,求能构造的这样的排列的方案数。
  • T组数据,每次给出一个n,求方案数%998244353。

思路:

  • 因为感觉条件比较苛刻,所以找一下规律,不难发现n>3时最后一项只能取1或n。
    对<=3的分类讨论,所以答案为 6 ∗ 2 n − 3 6*2^n-3 62n3, 快速幂即可。
  • 官方证明推导过程:

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL mod = 998244353;
LL pows(LL a, LL x, LL p)  if(x==0)return 1; LL t = pows(a, x>>1, p); if(x%2==0)return t*t%p; return t*t%p*a%p; 

int main()
    int T;  cin>>T;
    while(T--)
        LL n;  cin>>n;
        if(n==1 || n==2)cout<<n<<"\\n";
        else if(n==3)cout<<6<<"\\n";
        else cout<<6ll*pows(2,n-3,mod)%mod<<"\\n";
    
    return 0;


H.Three Integers

H. Three Integers
time limit per test1 second
memory limit per test512 megabytes
inputstandard input
outputstandard output
You are given three non-negative integers a, b, and c. Find three positive integers x, y, and z that satisfy xmody=a, ymodz=b, and zmodx=c.

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

Each test case contains 3 integers a, b, c (0≤a,b,c≤109) on a single line.

Output
For each test case, if there are such three integers satisfying the condition, output “YES”, then output the three integers x, y, z (1≤x,y,z≤1018) on the following line, or “NO” otherwise.

Example
inputCopy
4
0 0 0
1 2 3
6 6 6
11 3 3
outputCopy
YES
1 1 1
YES
5 2 8
NO
YES
11 45 14

题意:

  • 给定三个非负整数 a、b 和 c, 求三个正整数 x、y 和 z。
    满足x mod y = a,y mod z = b 且 z mod x = c。
  • 0 ≤ a, b, c ≤ 1000,000,000, 输出满足 1 ≤ x, y, z ≤ 10^18。

思路:

  • 先找特殊的,当三个值相等时,当且仅当a=b=c=0时有解,否则无解。
  • 然后列一下通式,x = k1y+a, y = k2z+b, z = k3x+c。
    套到一起可以发现 x = k1k2k3x + k1k2c + k1b + a,y=k2k3x+k2c+b,因为k1,k2,k3>0。
    所以可以得到k1, k2, k3中至少有一个为0, 即有一个值和输入的值相等
  • 不妨设x=a,然后只需要适当构造,取适当的 u,v 使得 z = ua+c > b 且 y = vz+b > a成立即可(构造方案不唯一)。
  • vp时是队友写的,构造方案大致是相邻两个数作差再特判一下。补题时发现网上有大佬分类讨论推出了全部的公式,直接套公式就能过,借鉴了一下。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
int main()
    int T;  cin>>T;
    while(T--)
        int a, b, c;  cin>>a>>b>>c;
        if(a==b && b==c)
            if(a!=0)cout<<"NO\\n";
            else cout<<"YES\\n1 1 1\\n";
            continue;
        
        LL x, y, z, k;  
        if(b > a)
            k = max(0, (c - a) / b) + 1;
            x = k * b + a;
            y = b;
            z = (k * b + a) * 2 + c;
        else if(a > c)
            k = max(0, (b - c) / a) + 1;
            x = a;
            y = (k * a + c) * 2 + b;
            z = k * a + c;
        else if(c > b)
            k = max(0, (a - b) / c) + 1;
            x = (k * c + b) * 2 + a;
            y = k * c + b;
            z = c;
        
        cout<<"YES\\n";
        cout<<x<<" "<<y<<" "<<z<<"\\n";
    
    return 0;

C.Necklace

C. Necklace
time limit per test1.0 s
memory limit per test512 megabytes
inputstandard input
outputstandard output
Bob has given Alice a necklace as her birthday gift. That necklace has N crystals, M of which catches her fancy. Formally, crystals with labels of 1…N are strung sequentially in a circle. And those catching her fancy are labelled n1,n2,…,nM.

Alice would like the necklace to be divided into M pieces. She asked Bob to sever the necklace into M pieces. Each piece should consist of a sequence of crystals as in the original necklace (i.e., the crystal labels are contiguous, except that 1 following N is accepted) and should include one crystal catching Alice’s fancy. Obviously, each crystal must belong to exactly one piece.

However, an excessively long piece of severed necklaces could not fit Alice’s slim neck. So she wants to know, among all possible severings as requested, what the minimum length of the longest piece from a severed necklace is. She wants you to answer this question.

Input
The first line of the input data contains 2 integers N and M (1≤M≤N<1018 and M≤106).

The second line contains M integers, the i-th of which represents ni. The ni’s are given in ascending order.

Output
You need to output your answer in one line.

Example
inputCopy
10 4
2 5 6 8
outputCopy
3
Note
As for the example: You can sever the necklace into [1,3],[4,5],[6,7],[8,10].

Considering huge scale of data, here is a way provided to help input faster:

#define gc()(is==it?it=(is=in)+fread(in,1,Q,stdin),(is==it?EOF:*is++):*is++)
const int Q=(1«24)+1;
char in[Q],*is=in,*it=in,c;
void read(long long &n)
  for(n=0;(c=gc())<'0'||c>'9';);
  for(;c<='9'&&c>='0';c=gc())n=n*10+c-48;

题意:

  • 长度为 n 的项链(是个环!)上有 m 个宝石,每个宝石要放在同一段里,求最长段长度的最小值。

思路:

  • 开始没看到是环,一眼二分答案想硬A上去,WA了两发才发现还有环这个操作。不过肯定还是二分答案+贪心的,就是贪心判断的方法需要改一下。

  • 每次check的时候从第一个位置开始贪心,一开始最大偏移量n-a[m]+a[1]-1,开个变量表示当前起始位置最大的偏移量,每跑一段区间都取个min,然后记录一下最开始的起始位置一共最大往前的偏移量即可。

  • 官方讲解:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    #define gc()(is==it?it=(is=in)+fread(in,1,Q,stdin),(is==it?EOF:*is++):*is++)
    const int Q=(1<<24)+1;
    char in[Q],*is=in,*it=in,c;
    void read(long long &n)
      for(n=0;(c=gc())<'0'||c>'9';);
      for(;c<='9'&&c>='0';c=gc())n=n*10+c-48;
    
    
    const int maxn = 1e6+10;
    LL n, m, a[maxn];
    int check(LL x)
        LL mx = n-(a[m]-a[1]+1), mm = 0;   //最大能往左边移的量, 当前左移的量
        LL lst = 0, mx0 = mx;              //后一段要给前一段的大小
        for(int i = 1; i < m; i++)
            LL now = x-lst;           //当前能分的=x-给了上一段的
            if(now<=0)return 0;       //当前能分的是负数或0了,寄
            LL cc = a[i+1]-a[i];      //当前需要分的
            if(cc>now)               //足够分
                lst = cc-now;         //分一下
                mx = min(mx, now-1);  //更新最大偏移
            else
                lst = 0;                 //不够分
                LL m3 = min(mx, now-cc); //往左边移
                mm += m3;                //累加左移的量
                mx = min(mx-m3, cc-1);   //更新最大偏移
            
        
        LL ed = lst+mx0+1-x;
        if(x-lst>=mx0+1 || mm>=ed)return 1;
        return 0;
    
    
    int main()
        read(n);  read(m);
        for(int i = 1; i <= m; i++)read(a[i]);
        LL l = 1, r = n; 
        while(l < r)
            LL mid = (l+r)>>1;
            if(check(mid))r = mid;
            else l = mid+1;
        
        cout<<l<<"\\n";
        return 0;
    
    

F.Cactus

F. Cactus
time limit per test1 second
memory limit per test512 megabytes
inputstandard input
outputstandard output
An undirected connected graph is called a cactus, if and only if each edge of it belongs to at most one simple cycle. A simple cycle is a cycle that has no repeated vertices.

Now suppose there are fn cactuses of n distinct vertices, and the cactuses may have parallel edges and must not have self-loops, you need to calculate ∑ni=1∏j≠i1+fi−fifjfi−fj.

The sum of a zero-length sequence is 0, and the product of a zero-length sequence is 1.

Input
A single line contains an integer n (1≤n≤3×105).

Output
Suppose the reduced form of the answer is xy, and you only need to output the value of x×y998244351mod998244353.

Example
inputCopy
2
outputCopy
1
Note
In the first example, f1=1,f2=2, and the answer is 1.

题意:

  • 官方

思路:

  • 一开始是没看懂f表示的意思(没想到仙人掌),就代了一下各种值,结果发现n=2和n=3的时候不管带进去什么值,式子算出来的结果都是一样的
  • 然后开始打表,验证了一下真的是代什么都一样,把n=1~20的结果都跑出来,很明显是个斐波那契数列,所以就直接O(n)扫一遍就好啦。
  • 官方证明:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 3e5+10;
const LL mod = 998244353;
LL f[maxn];
int main()
    LL n;  cin>>n;
    f[1] = f[2] = 1;
    for(int i = 3; i <= n; i++)
        f[i] = (f[i-1]+f[i-2])%mod;
    
    cout<<f[n]<<"\\n";
    return 0;

以上是关于2021第7届中国大学生程序设计竞赛CCPC广州站, 签到题4题的主要内容,如果未能解决你的问题,请参考以下文章

2021第7届中国大学生程序设计竞赛CCPC桂林站, 签到题5题

2021第7届中国大学生程序设计竞赛CCPC桂林站, 签到题5题

2022第8届中国大学生程序设计竞赛CCPC威海站, 签到题7题

2022第8届中国大学生程序设计竞赛CCPC威海站, 签到题7题

2022第8届中国大学生程序设计竞赛CCPC桂林站, 签到题4题

2022第8届中国大学生程序设计竞赛CCPC桂林站, 签到题4题