2021级新生个人训练赛第41场

问题 A: 数字统计I

题目描述
请统计某个给定范围[L,R]的所有整数中,数字2出现的次数。
比如给定范围[2,22],数字2在数2中出现了1次,在数12中出现1次,在数20中出现1次,在数21中出现1次,在数22中出现2次,所以数字2在该范围内一共出现了6次。
输入
输入共1行,为两个正整数L和R(1≤L≤R≤10000),之间用一个空格隔开。
输出
输出共1行,表示数字2出现的次数。
样例输入 Copy
2 22
样例输出 Copy
6

暴力判断即可

#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
# include<bits/stdc++.h>
# include<unordered_map>
 
# define eps 1e-9
# define fi first
# define se second
# define ll long long
# define int ll
# define x1 sb
# define y1 dsb
# define x2 ssb
# define y2 ddsb
// cout<<fixed<<setprecision(n) 
//bool operator<(const Node& x )
using namespace std;
typedef unsigned long long ull;
typedef pair<int,int > PII; 
const int mod=1e9+7;
const int N=2e6+10;
const int Time=86400;
const int X=131;
const int inf=0x3f3f3f3f;
const double PI = 1e-4;
double pai = 3.14159265358979323846; 
double e = exp(1);
 
int T,n,m,k,ans,x1,y1,x2,y2;
int x[N],y[N];
int a[505][505];
void solve(){
          int l , r;
          cin >> l >> r;
          for(int i = l ; i <= r ; i ++ ){
               int x = i;
               while(x){
                     if(x%10 == 2) ans++;
                     x/=10;
                 }
          }
          cout<<ans;
 }
/*
 
*/
signed main(){  
    std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); 
    // cin >> T;
     T = 1;
    while(T--){
        solve();
    } 
    return 0; 
}

问题 B: 接水问题

题目描述
学校里有一个水房,水房里一共装有m个龙头可供同学们打开水,每个龙头每秒钟的供水量相等,均为1。

现在有n名同学准备接水,他们的初始接水顺序已经确定。将这些同学按接水顺序从1到n编号,i号同学的接水量为wi。接水开始时,1到m号同学各占一个水龙头,并同时打开水龙头接水。当其中某名同学j完成其接水量要求wj后,下一名排队等候接水的同学k马上接替j同学的位置开始接水。这个换人的过程是瞬间完成的,且没有任何水的浪费。即j同学第x秒结束时完成接水,则k同学第x+1秒立刻开始接水。若当前接水人数n’不足m,则只有n’个龙头供水,其它m−n’个龙头关闭。

现在给出n名同学的接水量,按照上述接水规则,问所有同学都接完水需要多少秒。
输入
第1行2个整数n和m,用一个空格隔开,分别表示接水人数和龙头个数。
第2行n个整数w1、w2、……、wn,每两个整数之间用一个空格隔开,wi表示i号同学的接水量。
1≤n≤10000,1≤m≤100且m≤n;1≤wi≤100。
输出
输出只有一行,1个整数,表示接水所需的总时间。
样例输入 Copy
5 3
4 4 1 2 1
样例输出 Copy
4
提示
第1秒,3人接水。第1秒结束时,1、2、3号同学每人的已接水量为1,3号同学接完水,4号同学接替3号同学开始接水。
第2秒,3人接水。第2秒结束时,1、2号同学每人的已接水量为2,4号同学的已接水量为1。
第3秒,3人接水。第3秒结束时,1、2号同学每人的已接水量为3,4号同学的已接水量为2。4号同学接完水,5号同学接替4号同学开始接水。
第4秒,3人接水。第4秒结束时,1、2号同学每人的已接水量为4,5号同学的已接水量为1。1、2、5号同学接完水,即所有人完成接水。
总接水时间为4秒。

因为已经固定了接水顺序,所以只需要模拟即可,思路就是每1s减去m个当前水龙头下水一次,然后如果等于0了就换第m+1……一直到第n+m即可

#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
# include<bits/stdc++.h>
# include<unordered_map>
 
# define eps 1e-9
# define fi first
# define se second
# define ll long long
# define int ll
# define x1 sb
# define y1 dsb
# define x2 ssb
# define y2 ddsb
// cout<<fixed<<setprecision(n) 
//bool operator<(const Node& x )
using namespace std;
typedef unsigned long long ull;
typedef pair<int,int > PII; 
const int mod=1e9+7;
const int N=2e6+10;
const int Time=86400;
const int X=131;
const int inf=0x3f3f3f3f;
const double PI = 1e-4;
double pai = 3.14159265358979323846; 
double e = exp(1);
 
int T,n,m,k,ans,x1,y1,x2,y2;
int x[N],y[N];
int a[N];
void solve(){
           cin >> n >> m;
           for(int  i = 1 ; i <= n ; i ++ ) cin >> a[i];
           k = m + 1;
           while(k <= n + m){
                for(int i = 1 ; i <= m ; i ++ ){
                       a[i]--;
                       if(a[i] == 0){
                               a[i] = a[k];
                               k++;
                          }
                   }
                   ans++;
           }
           cout<<ans;
 }
/*
 
*/
signed main(){  
    std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); 
    // cin >> T;
     T = 1;
    while(T--){
        solve();
    } 
    return 0; 
}

问题 C: 导弹拦截

题目描述
经过11年的韬光养晦,某国研发出了一种新的导弹拦截系统,凡是与它的距离不超过其工作半径的导弹都能够被它成功拦截。当工作半径为0时,则能够拦截与它位置恰好相同的导弹。但该导弹拦截系统也存在这样的缺陷:每套系统每天只能设定一次工作半径。而当天的使用代价,就是所有系统工作半径的平方和。

某天,雷达捕捉到敌国的导弹来袭。由于该系统尚处于试验阶段,所以只有两套系统投入工作。如果现在的要求是拦截所有的导弹,请计算这一天的最小使用代价。
输入
第一行包含4个整数x1、y1、x2、y2,每两个整数之间用一个空格隔开,表示这两套导弹拦截系统的坐标分别为(x1,y1)、(x2,y2)。
第二行包含1个整数N(1≤N≤100000),表示有N颗导弹。接下来N行,每行两个整数x、y,中间用一个空格隔开,表示一颗导弹的坐标(x,y)。不同导弹的坐标可能相同。
输出
输出只有一行,包含一个整数,即当天的最小使用代价。
样例输入 Copy
0 0 10 0
2
-3 3
10 0
样例输出 Copy
18
提示
两个点(x1,y1)、(x2,y2)之间距离的平方是(x1−x2)2+(y1−y2)2。
两套系统工作半径r1、r2的平方和,是指r1、r2分别取平方后再求和,即r12+r22。

对于100%的数据,1≤N≤100000,且所有坐标分量的绝对值都不超过1000。

思路:我们可以先求出一颗导弹到所有点的距离,然后排序,此时第i的距离代表前i个点到第一个导弹的最大距离;我们可以再求一下第i+1个点到第二号导弹的最大距离。因为我们已经排好序,所以第i+1到第一个导弹的距离肯定比第i个距离远,那我们只要枚举一下1~n计算第i个点到第二个导弹的最远距离,然后等价于求所有 前缀i + 后缀i 的最小值,可以代码再理解理解。

#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
# include<bits/stdc++.h>
# include<unordered_map>
 
# define eps 1e-9
# define fi first
# define se second
# define ll long long
# define int ll
# define x1 sb
# define y1 dsb
# define x2 ssb
# define y2 ddsb
// cout<<fixed<<setprecision(n) 
//bool operator<(const Node& x )
using namespace std;
typedef unsigned long long ull;
typedef pair<int,int > PII; 
const int mod=1e9+7;
const int N=2e6+10;
const int Time=86400;
const int X=131;
const int inf=0x3f3f3f3f;
const double PI = 1e-4;
double pai = 3.14159265358979323846; 
double e = exp(1);
 
int T,n,m,k,ans,x1,y1,x2,y2;
int x[N],y[N];
struct Node{
    int d1;
    int d2;
    int i;
    bool operator<(const Node& x){
        return d1 < x.d1;
    }
}a[N];
int qsm(int a,int b){
     int res = 1;
     while(b){
          if(b&1) res = res * a;
          a = a * a;
          b >>= 1; 
     }
     return res;
}
void solve(){
        ans = inf;
        cin >> x1 >> y1 >> x2 >> y2;
        cin >> n;
        for(int i = 1 ; i <= n ; i ++ ){
              cin >> x[i] >> y[i];
              a[i].d1 = qsm(x[i]-x1,2) + qsm(y[i]-y1,2);
              a[i].i = i;
        }
        sort(a+1,a+1+n);
        for(int i = n ; i >= 1 ; i --){
             int dis = qsm(x[a[i].i]-x2,2) + qsm(y[a[i].i]-y2,2);
             a[i].d2 = max(dis,a[i+1].d2);
        }
        for(int i = 0 ; i <= n ; i ++ ){
              ans = min(ans,a[i].d1+a[i+1].d2);
        }
        cout<<ans;
 }
/*
 
*/
signed main(){  
    std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); 
    // cin >> T;
     T = 1;
    while(T--){
        solve();
    } 
    return 0; 
}

问题 D: 三国游戏

题目描述
小涵很喜欢电脑游戏,这些天他正在玩一个叫做《三国》的游戏。

在游戏中,小涵和计算机各执一方,组建各自的军队进行对战。游戏中共有 N 位武将(N为偶数且不小于 4),任意两个武将之间有一个“默契值”,表示若此两位武将作为一对组合作战时,该组合的威力有多大。游戏开始前,所有武将都是自由的(称为自由武将,一旦某个自由武将被选中作为某方军队的一员,那么他就不再是自由武将了),换句话说,所谓的自由武将不属于任何一方。游戏开始,小涵和计算机要从自由武将中挑选武将组成自己的军队,规则如下:小涵先从自由武将中选出一个加入自己的军队,然后计算机也从自由武将中选出一个加入计算机方的军队。接下来一直按照“小涵→计算机→小涵→……”的顺序选择武将,直到所有的武将被双方均分完。然后,程序自动从双方军队中各挑出一对默契值最高的武将组合代表自己的军队进行二对二比武,拥有更高默契值的一对武将组合获胜,表示两军交战,拥有获胜武将组合的一方获胜。

已知计算机一方选择武将的原则是尽量破坏对手下一步将形成的最强组合,它采取的具体策略如下:任何时刻,轮到计算机挑选时,它会尝试将对手军队中的每个武将与当前每个自由武将进行一一配对,找出所有配对中默契值最高的那对武将组合,并将该组合中的自由武将选入自己的军队。

下面举例说明计算机的选将策略,例如,游戏中一共有 6 个武将,他们相互之间的默契值如下表所示
在这里插入图片描述

双方选将过程如下所示:
在这里插入图片描述

小涵想知道,如果计算机在一局游戏中始终坚持上面这个策略,那么自己有没有可能必胜?如果有,在所有可能的胜利结局中,自己那对用于比武的武将组合的默契值最大是多少? 假设整个游戏过程中,对战双方任何时候均能看到自由武将队中的武将和对方军队的武将。为了简化问题,保证对于不同的武将组合,其默契值均不相同。
输入
输入共N行(N≤500)。
第一行为一个偶数N,表示武将的个数。
第2行到第N行里,第(i+1)行有(N−i)个非负整数,每两个数之间用一个空格隔开,表示i号武将和i+1,i+2,……,N号武将之间的默契值(0≤默契值≤1,000,000,000)。
输出
输出共1或2行。
若对于给定的游戏输入,存在可以让小涵获胜的选将顺序,则输出1,并另起一行输出所有获胜的情况中,小涵最终选出的武将组合的最大默契值。
如果不存在可以让小涵获胜的选将顺序,则输出0。
样例输入 Copy
6
5 28 16 29 27
23 3 20 1
8 32 26
33 11
12
样例输出 Copy
1
32

首先我们选定一个i,我们知道我们一定拿不到这一行或者这一列的最大值,但是我们可以拿次大值,然后之后我们一定可以拿到 新的最大值。所以我们只需要对每一行排序,找到次大值,那个答案就是我们要求的。当然我们是不可能输的,所以没有输出0的情况

#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
# include<bits/stdc++.h>
# include<unordered_map>
 
# define eps 1e-9
# define fi first
# define se second
# define ll long long
# define int ll
# define x1 sb
# define y1 dsb
# define x2 ssb
# define y2 ddsb
// cout<<fixed<<setprecision(n) 
//bool operator<(const Node& x )
using namespace std;
typedef unsigned long long ull;
typedef pair<int,int > PII; 
const int mod=1e9+7;
const int N=2e6+10;
const int Time=86400;
const int X=131;
const int inf=0x3f3f3f3f;
const double PI = 1e-4;
double pai = 3.14159265358979323846; 
double e = exp(1);
 
int T,n,m,k,ans,x1,y1,x2,y2;
int x[N],y[N];
int a[505][505];
void solve(){
           cin >> n;
           for(int i = 1 ; i <= n - 1 ; i ++)
            for(int j = i + 1 ; j <= n ;  j ++ )
             cin >> a[i][j],a[j][i] = a[i][j];
             
            for(int i = 1 ; i <= n ; i ++ ){
                  sort(a[i]+1,a[i]+1+n);
                  ans = max(ans,a[i][n-1]);
            }
            cout<<1<<"\n"<<ans;
 }
/*
 
*/
signed main(){  
    std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); 
    // cin >> T;
     T = 1;
    while(T--){
        solve();
    } 
    return 0; 
}

问题 E: ABCxxx

题目描述
This contest, AtCoder Beginner Contest, is abbreviated as ABC.
When we refer to a specific round of ABC, a three-digit number is appended after ABC. For example, ABC680 is the 680th round of ABC.
What is the abbreviation for the N-th round of ABC? Write a program to output the answer.

Constraints
100≤N≤999
输入
Input is given from Standard Input in the following format:
N
输出
Print the abbreviation for the N-th round of ABC.
样例输入 Copy
100
样例输出 Copy
ABC100
提示
The 100th round of ABC is ABC100.

思路:直接输出就行

#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
# include<bits/stdc++.h>
# include<unordered_map>
 
# define eps 1e-9
# define fi first
# define se second
# define ll long long
# define int ll
# define x1 sb
# define y1 dsb
# define x2 ssb
# define y2 ddsb
// cout<<fixed<<setprecision(n) 
//bool operator<(const Node& x )
using namespace std;
typedef unsigned long long ull;
typedef pair<int,int > PII; 
const int mod=1e9+7;
const int N=2e6+10;
const int Time=86400;
const int X=131;
const int inf=0x3f3f3f3f;
const double PI = 1e-4;
double pai = 3.14159265358979323846; 
double e = exp(1);
 
int T,n,m,k,ans,x1,y1,x2,y2;
int x[N],y[N];
int a[N];
void solve(){
          cin >> n;
          cout<<"ABC"<<n;
 }
/*
 
*/
signed main(){  
    std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); 
    // cin >> T;
     T = 1;
    while(T--){
        solve();
    } 
    return 0; 
}

问题 F: Break Number

题目描述
Takahashi loves numbers divisible by 2.
You are given a positive integer N. Among the integers between 1 and N (inclusive), find the one that can be divisible by 2 for the most number of times. The solution is always unique.
Here, the number of times an integer can be divisible by 2, is how many times the integer can be divided by 2 without remainder.
For example,
6 can be divided by 2 once: 6 -> 3.
8 can be divided by 2 three times: 8 -> 4 -> 2 -> 1.
3 can be divided by 2 zero times.

Constraints
1≤N≤100
输入
Input is given from Standard Input in the following format:
N
输出
Print the answer.
样例输入 Copy
7
样例输出 Copy
4
提示
4 can be divided by 2 twice, which is the most number of times among 1, 2, …, 7.

思路:n只有100直接暴力判断即可

#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
# include<bits/stdc++.h>
# include<unordered_map>
 
# define eps 1e-9
# define fi first
# define se second
# define ll long long
# define int ll
# define x1 sb
# define y1 dsb
# define x2 ssb
# define y2 ddsb
// cout<<fixed<<setprecision(n) 
//bool operator<(const Node& x )
using namespace std;
typedef unsigned long long ull;
typedef pair<int,int > PII; 
const int mod=1e9+7;
const int N=2e6+10;
const int Time=86400;
const int X=131;
const int inf=0x3f3f3f3f;
const double PI = 1e-4;
double pai = 3.14159265358979323846; 
double e = exp(1);
 
int T,n,m,k,ans,x1,y1,x2,y2;
int x[N],y[N];
int a[N];
void solve(){
          cin >> n;
          for(int i = 1 ; i <= n ; i ++ ){
              int x = i,sum=0;
              while(x){
                    sum++;
                    x/=2;
                }
              if(sum > ans){
                   ans = sum;
                   k = i;
              }
          }
          cout<<k;
 }
/*
 
*/
signed main(){  
    std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); 
    // cin >> T;
     T = 1;
    while(T--){
        solve();
    } 
    return 0; 
}

问题 G: Cat Snuke and a Voyage

题目描述
In Takahashi Kingdom, there is an archipelago of N islands, called Takahashi Islands. For convenience, we will call them Island 1, Island 2, …, Island N.
There are M kinds of regular boat services between these islands. Each service connects two islands. The i-th service connects Island ai and Island bi.
Cat Snuke is on Island 1 now, and wants to go to Island N. However, it turned out that there is no boat service from Island 1 to Island N, so he wants to know whether it is possible to go to Island N by using two boat services.
Help him.

Constraints
3≤N≤200 000
1≤M≤200 000
1≤ai<bi≤N
(ai,bi)≠(1,N)
If i≠j, (ai,bi)≠(aj,bj).
输入
Input is given from Standard Input in the following format:
N M
a1 b1
a2 b2
:
aM bM
输出
If it is possible to go to Island N by using two boat services, print POSSIBLE; otherwise, print IMPOSSIBLE.
样例输入 Copy
3 2
1 2
2 3
样例输出 Copy
POSSIBLE

思路:枚举1能到的所有点能不能到n就行
本来想写线性的,结果写成了n^2的,但是还过了,速度还行。那就算了不写了就这样,能过的代码都是好代码

#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
# include<bits/stdc++.h>
# include<unordered_map>
 
# define eps 1e-9
# define fi first
# define se second
# define ll long long
# define int ll
# define x1 sb
# define y1 dsb
# define x2 ssb
# define y2 ddsb
// cout<<fixed<<setprecision(n) 
//bool operator<(const Node& x )
using namespace std;
typedef unsigned long long ull;
typedef pair<int,int > PII; 
const int mod=1e9+7;
const int N=2e6+10;
const int Time=86400;
const int X=131;
const int inf=0x3f3f3f3f;
const double PI = 1e-4;
double pai = 3.14159265358979323846; 
double e = exp(1);
 
int T,n,m,k,ans,x1,y1,x2,y2;
int x[N],y[N];
int a[N];
vector<int>g[N];
void solve(){
          cin >> n >> m;
          for(int i =  1; i <= m ; i ++ ){
               int u,v;
               cin >> u >> v;
               g[u].push_back(v);
               g[v].push_back(u);
          }
          for(auto i : g[1]){
            for(auto j : g[i]){
                 if(j == n){
                      cout<<"POSSIBLE";
                      return ;
                   }
              }
          }
          cout<<"IMPOSSIBLE";
 }
/*
 
*/
signed main(){  
    std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); 
    // cin >> T;
     T = 1;
    while(T--){
        solve();
    } 
    return 0; 
}

问题 H: Decrease (Judge ver.)

题目描述
We have a sequence of length N consisting of non-negative integers. Consider performing the following operation on this sequence until the largest element in this sequence becomes N−1 or smaller. (The operation is the same as the one in Problem D.)
Determine the largest element in the sequence (if there is more than one, choose one). Decrease the value of this element by N, and increase each of the other elements by 1.
It can be proved that the largest element in the sequence becomes N−1 or smaller after a finite number of operations.
You are given the sequence ai. Find the number of times we will perform the above operation.

Constraints
2≤N≤50
0≤ai≤1016+1000

输入
Input is given from Standard Input in the following format:
N
a1 a2 … aN

输出
Print the number of times the operation will be performed.
样例输入 Copy
4
3 3 3 3
样例输出 Copy
0

思路:用大根堆进行模拟,每次取最大值,然后减去m次操作,然后对于其他的所有值都+k,对于第1个数相当于+0,第二个数相当于+1,所以每次放进去的时候要-k,n很小直接暴力模拟就可以,优先队列模拟方便,数组模拟写起来麻烦

#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
# include<bits/stdc++.h>
# include<unordered_map>
 
# define eps 1e-9
# define fi first
# define se second
# define ll long long
# define int ll
// cout<<fixed<<setprecision(n) 
//bool operator<(const Node& x )
using namespace std;
typedef unsigned long long ull;
typedef pair<int,int > PII; 
const int mod=1e9+7;
const int N=2e6+10;
const int Time=86400;
const int X=131;
const int inf=0x3f3f3f3f;
const double PI = 1e-4;
double pai = 3.14159265358979323846; 
double e = exp(1);
 
int T,n,m,k,ans1,ans,sum,cnt1,cnt2;
int a[N],b[N];
priority_queue<int,vector<int>,less<int>>q;
 
void solve(){
      cin >> n ;
      for(int i = 1 ; i <= n ; i ++ ){
           cin >> a[i];
           q.push(a[i]);
      }      
      k = 0;
      while(q.size()){
          auto now = q.top() + k;
          q.pop();
          if(now <= n - 1) break;
          m = now / n;
          now -= m * n;
          k+=m;
          q.push(now-k);
      } 
      cout<<k;
         
 }
/*
 
*/
signed main(){  
    std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); 
    // cin >> T;
     T = 1;
    while(T--){
        solve();
    } 
    return 0; 
}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值