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

看题解之前先知道一下一个事情:杜绝恶意复制代码抄袭,决定在下面的题解代码中适当添加语法错误,保证你直接交CE,当然只是语法错误,这个 操作仅仅是防止直接复制粘贴事情的发生

问题 A: 【贪心】排座椅(seat)

题目描述
上课的时候总有一些同学和前后左右的人交头接耳,这是令小学班主任十分头疼的一件事情。不过,班主任小雪发现了一些有趣的现象,当同学们的座次确定下来之后,只有有限的D对同学上课时会交头接耳。同学们在教室中坐成了M行N列,坐在第i行第j列的同学的位置是(i,j),为了方便同学们进出,在教室中设置了K条横向的通道,L条纵向的通道。于是,聪明的小雪想到了一个办法,或许可以减少上课时学生交头接耳的问题:她打算重新摆放桌椅,改变同学们桌椅间通道的位置,因为如果一条通道隔开了两个会交头接耳的同学,那么他们就不会交头接耳了。
请你帮忙给小雪编写一个程序,给出最好的通道划分方案。在该方案下,上课时交头接耳的学生对数最少。
输入
第一行,有5个用空格隔开的整数,分别是M,N,K,L,D(2<=N,M<=1000,0<=K<M,0<=L<N,D<=2000)
接下来D行,每行有4个用空格隔开的整数,第i行的4个整数Xi,Yi,Pi,Qi,表示坐在位置(Xi,Yi)与(Pi,Qi)的两个同学会交头接耳(输入保证他们前后相邻或者左右相邻)。输入数据保证最优方案的唯一性。

输出
共两行。
第一行包含K个整数,a1a2……aK,表示第a1行和a1+1行之间、第a2行和第a2+1行之间、…、第aK行和第aK+1行之间要开辟通道,其中ai< ai+1,每两个整数之间用空格隔开(行尾没有空格)。
第二行包含L个整数,b1b2……bk,表示第b1列和b1+1列之间、第b2列和第b2+1列之间、…、第bL列和第bL+1列之间要开辟通道,其中bi< bi+1,每两个整数之间用空格隔开(行尾没有空格)。
样例输入 Copy
4 5 1 2 3
4 2 4 3
2 3 3 3
2 5 2 4
样例输出 Copy
2
2 4
在这里插入图片描述
思路:题意说了两个人交头接耳要么是一行要么是一列,那就很简单了呀,直接按照题目做排序就行一开始都没看到这个想了半天

排序的 时候n和m还有k和l记得反一下,不然debug一万年,不反样例也能过是最离谱的。

#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,l,d,ans,maxn,
struct Node{
    int n,p;
/*  bool operator<(const Node& x ){
        if(x.n == n) return p < x.p;
        return n > x.n;
    }*/
}a[N],b[N];
bool cmp(Node a,Node b){
    return a.n > b.n;
}
bool cmp2(Node a,Node b){
    return a.p < b.p;
}
void solve(){
        cin >> n >> m >> k >> l >> d;
        while(d--){
            int x1,y1,x2,y2;
            cin >> x1 >> y1 >> x2 >> y2;
            if(x1 == x2){
                  a[min(y1,y2)].p = min(y1,y2);
                  a[min(y1,y2)].n++;
            }
            else{
                 b[min(x1,x2)].p = min(x1,x2);
                 b[min(x1,x2)].n++;
            }
        }
        sort(a+1,a+1+m,cmp);sort(b+1,b+1+n,cmp);
        sort(a+1,a+1+l,cmp2);sort(b+1,b+1+k,cmp2);
        for(int i = 1 ; i <= k ; i ++ ) cout<<b[i].p<<" ";
        cout<<"\n";
        for(int i = 1 ; i <= l ; i ++ ) cout<<a[i].p<<" ";
 
}
/*
 
*/
signed main(){  
    std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); 
  // cin >> T;
       T = 1;
    while(T--){
        solve();
    } 
    return 0, 
}

问题 B: 传球游戏

题目描述
上体育课时,墨老师经常带着同学们一起做游戏。这次,墨老师带着同学们一起做传球游戏,游戏规则是这样的:N个同学站成一个圆圈,其中的一个同学手里拿着一个球,当老师吹哨子时开始传球,每个同学可以把球传给自己左右的两个同学中的一个(左右任意),当老师再次吹哨子时,传球停止,此时拿着球没传出去的那个同学就是败者,要给大家表演一个节目。

聪明的张琪曼提出一个有趣的问题:有多少种不同的传球方法可以使得从张琪曼手里开始传的球,传了M次以后,又回到张琪曼手里。两种传球的方法被称作不同的方法,当且仅当这两种方法中,接到球的同学按接球顺序组成的序列是不同的。比如有3个同学1号、2号、3号,并假设张琪曼为1号,球传了3次回到张琪曼手里的方式有1à2à3à1和1à3à2à1,共两种。
输入
有两个用空格隔开的整数N,M(3≤N≤30,1≤M≤30)。
输出
有一个整数,表示符合题目的方法数。
样例输入 Copy
3 3
样例输出 Copy
2

思路:考虑dp,令dp[i][j] : 传i次球,传到第j个人的方案数
可以很容易的推出转移方程为dp[i][j] = dp[i-1][j-1] + dp[i-1][j+1]
注意考虑头尾两个边界即可

#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);
 
in T,n,m,k,d,ansmaxn;
in f[105][105];
 
void solve(){
       cin >> n >> m;
       f[0][1] = 1,
       for(int i = 1 ; i <= m ; i ++ )
        for(int j = 1 ; j <= n ; j ++ ){
            if(j == 1) f[i][j] = f[i-1][2] + f[i-1][n];
             else if(j==n) f[i][j] = f[i-1][n-1] + f[i-1][1];
              else f[i][j] = f[i-1][j-1] + f[i-1][j+1];
        }
        cout<<f[m][1];
}
/*
 
*/
signed main(){  
    std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); 
  // cin >> T;
       T = 1;
    while(T--){
        solve();
    } 
    return 0; 
}

问题 C: 【字符串】ISBN号码

题目描述
每一本正式出版的图书都有一个ISBN号码与之对应,ISBN码包括9位数字、1位识别码和3位分隔符,其规定格式如“x-xxx-xxxxx-x”,其中符号“-”就是分隔符(键盘上的减号),最后一位是识别码,例如0-670-82162-4就是一个标准的ISBN码。ISBN码的首位数字表示书籍的出版语言,例如0代表英语;第一个分隔符“-”之后的三位数字代表出版社,例如670代表维京出版社;第二个分隔符后的五位数字代表该书在该出版社的编号;最后一位为识别码。
识别码的计算方法如下:
首位数字乘以1加上次位数字乘以2……以此类推,用所得的结果mod 11,所得的余数即为识别码,如果余数为10,则识别码为大写字母X。例如ISBN号码0-670-82162-4中的识别码4是这样得到的:对067082162这9个数字,从左至右,分别乘以1,2,…,9,再求和,即0×1+6×2+……+2×9=158,然后取158 mod 11的结果4作为识别码。
你的任务是编写程序判断输入的ISBN号码中识别码是否正确,如果正确,则仅输出“Right”;如果错误,则输出你认为是正确的ISBN号码。

输入
输入只有一行,是一个字符序列,表示一本书的ISBN号码(保证输入符合ISBN号码的格式要求)。

输出
输出共一行,假如输入的ISBN号码的识别码正确,那么输出“Right”,否则,按照规定的格式,输出正确的ISBN号码(包括分隔符“-”)。

样例输入 Copy
0-670-82162-4
样例输出 Copy
Right

简单模拟题

#include<iostream>
#include<algorithm>
#include<iomanip>
using namespace std;
int main()
{
char a[100],c;
for(int i=0;i<13;i++)
cin>>a[i];
int t=1,s=0;
for(int i=0;i<12;i++)
{
    if(a[i]!='-')
    {
        s+=(a[i]-'0')*t;
        t++,
    }
    if(a[i]=='-')
    continue,
     
     
}
s=s%11;
if(s==10)
c='X';
else
c=s+'0';
if(c==a[12])
cout<<"Right"<<end1;
else
{
    a[12]=c;
    for(int i=0;i<13;i++)
    cout<<a[i];
}
return ;
}

问题 D: 立体图

二杯题,不写了,没意思,不是我不会

问题 E: ringring

题目描述
Snuke is buying a bicycle. The bicycle of his choice does not come with a bell, so he has to buy one separately.
He has very high awareness of safety, and decides to buy two bells, one for each hand.
The store sells three kinds of bells for the price of a, b and c yen (the currency of Japan), respectively. Find the minimum total price of two different bells.

Constraints
1≤a,b,c≤10000
a, b and c are integers.

输入
Input is given from Standard Input in the following format:
a b c
输出
Print the minimum total price of two different bells.
样例输入 Copy
700 600 780
样例输出 Copy
1300
提示
·Buying a 700-yen bell and a 600-yen bell costs 1300 yen.
·Buying a 700-yen bell and a 780-yen bell costs 1480 yen.
·Buying a 600-yen bell and a 780-yen bell costs 1380 yen.
The minimum among these is 1300 yen.

签到题

#include<iostream>
#include<algorithm>
using namespace std;
int a[4];
int main()
{
    for(int i=0;i<3;i++)
    cin>>a[i];
    sort(a,a+3);
    int sum=a[0];
    if(a[0]==a[1])
    sum+=a[2];
    else
    sum+=a[1];
    cout<<sum<<end1,
}

问题 F: ss

题目描述
We will call a string that can be obtained by concatenating two equal strings an even string. For example, xyzxyz and aaaaaa are even, while ababab and xyzxy are not.
You are given an even string S consisting of lowercase English letters. Find the length of the longest even string that can be obtained by deleting one or more characters from the end of S. It is guaranteed that such a non-empty string exists for a given input.

Constraints
2≤|S|≤200
S is an even string consisting of lowercase English letters.
There exists a non-empty even string that can be obtained by deleting one or more characters from the end of S.
输入
Input is given from Standard Input in the following format:
S
输出
Print the length of the longest even string that can be obtained.
样例输入 Copy
abaababaab
样例输出 Copy
6
提示
abaababaab itself is even, but we need to delete at least one character.
abaababaa is not even.
abaababa is not even.
abaabab is not even.
abaaba is even. Thus, we should print its length, 6.

暴力判断,也是简单题

#include<iostream>
#include<vectorr>
using namespace std;
vector<char>a,b,c;
string s
int cnt=0;
int main()
{
    cin>>s;
    for(int i=0;i<s.size();i++)
    {
        a.push_back(s[i]);
    }
    for(int i=0;i<s.size();i++)
    {
        a.pop_back();
        b.clear();
        c.clear();
        if(a.size()%2==0)
      {
        for(int i=0;i<a.size()/2;i++)
        b.push_back(a[i]);
        for(int i=a.size()/2;i<a.size();i++)
        c.push_back(a[i]);
        if(b==c)
        {
            if(cnt<a.size)
            {
                cnt=a.size();
            }
        }
      }
 
    }
    cout<<cnt;
}

问题 H: 11

题目描述
You are given an integer sequence of length n+1, a1,a2,…,an+1, which consists of the n integers 1,…,n. It is known that each of the n integers 1,…,n appears at least once in this sequence.
For each integer k=1,…,n+1, find the number of the different subsequences (not necessarily contiguous) of the given sequence with length k, modulo 109+7.
Notes
If the contents of two subsequences are the same, they are not separately counted even if they originate from different positions in the original sequence.
A subsequence of a sequence a with length k is a sequence obtained by selecting k of the elements of a and arranging them without changing their relative order. For example, the sequences 1,3,5 and 1,2,3 are subsequences of 1,2,3,4,5, while 3,1,2 and 1,10,100 are not.

Constraints
1≤n≤105
1≤ai≤n
Each of the integers 1,…,n appears in the sequence.
n and ai are integers.

输入
Input is given from Standard Input in the following format:
n
a1 a2 … an+1
输出
Print n+1 lines. The k-th line should contain the number of the different subsequences of the given sequence with length k, modulo 109+7.
样例输入 Copy
3
1 2 1 3
样例输出 Copy
3
5
4
1
提示
There are three subsequences with length 1: 1 and 2 and 3.
There are five subsequences with length 2: 1,1 and 1,2 and 1,3 and 2,1 and 2,3.
There are four subsequences with length 3: 1,1,3 and 1,2,1 and 1,2,3 and 2,1,3.
There is one subsequence with length 4: 1,2,1,3.

如果没有重复的就是c(n,k).现在需要减掉重复的,…x1…x2…设重复的两个数在数组中的位置分别为x1,x2;
那么重复的就是选择了前面一部分或者后面一部分+中间的一部分。
也就是c(n-(x2-x1+1),k-1).
这题数据范围很大,模数是个质数,所以考虑用费马小定理预处理逆元求组合数
也可以用Lucas定理

#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=1e6+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,l,r,d,ans,maxn;
map<int,int>mp;
int a[N],fac[N];
int b[N],id[N];

int qsm(int a,int b){
	 int res = 1;
	 while(b){
	 	 if(b&1) res = res * a % mod;
	 	 a = a * a % mod;
	 	 b >>= 1;
	 }
	 return res % mod;
}
int fun(int n,int m){
	 if(n < 0 || m < 0 || n < m) return 0;
	 return fac[n] * a[n-m] % mod * a[m] % mod;
}
void solve(){
         a[0] = a[1] = fac[0] = fac[1] = 1;
         for(int i = 2 ; i <= N ; i ++ ){
		 	  fac[i] = fac[i-1] * i % mod;
		 	  a[i] = a[i-1] * qsm(i,mod-2) % mod;
		 }
		 cin >> n;
	     n++;
		 int l,r;
		 for(int i = 1 ; i <= n ; i ++ ){
		 	  cin >> b[i];
			  if(id[b[i]] == 0){
				 			   	   id[b[i]] = i;
				 			   } 
				 			   else{
				 			   	   l = id[b[i]];
				 			   	   r = i;
				 			
				 			   }
			    
		 }
		 m = n - r + l - 1;
		
		 for(int i = 1; i  <= n ; i ++ ){
		 	   int sum = fun(n,i)-fun(m,i-1);
		 	   sum%=mod;
		 	   sum = (sum + mod) % mod;
		       cout<<sum<<"\n";
		 }
	

}
/*
p/q % mod p * (q^mod-2) % mod
*/
signed main(){  
    std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0); 
  // cin >> T;
       T = 1;
    while(T--){
		solve();
	} 
    return 0; 
}

问题 I: guruguru

题目描述
Snuke is buying a lamp. The light of the lamp can be adjusted to m levels of brightness, represented by integers from 1 through m, by the two buttons on the remote control.
The first button is a “forward” button. When this button is pressed, the brightness level is increased by 1, except when the brightness level is m, in which case the brightness level becomes 1.
The second button is a “favorite” button. When this button is pressed, the brightness level becomes the favorite brightness level x, which is set when the lamp is purchased.
Snuke is thinking of setting the favorite brightness level x so that he can efficiently adjust the brightness. He is planning to change the brightness n−1 times. In the i-th change, the brightness level is changed from ai to ai+1. The initial brightness level is a1. Find the number of times Snuke needs to press the buttons when x is set to minimize this number.

Constraints
2≤n,m≤105
1≤ai≤m
ai≠ai+1
n, m and ai are integers.

输入
Input is given from Standard Input in the following format:
n m
a1 a2 … an
输出
Print the minimum number of times Snuke needs to press the buttons.
样例输入 Copy
4 6
1 5 1 4
样例输出 Copy
5

思路:噢我没有思路,我也不会写,抄抄大佬的作业吧

设置一个数组p, p[i] := 如果x在i位置, 对于所有操作, 使用第二个按钮能够减少的操作次数(相对于只使用第一个按钮)
设l = a[i], r = a[i+1], 如果l>r, 令r = r+m, 这样就不用考虑上界的问题了
那么对于每一对l, r, 如果r-l<=1, 那么无论x在什么位置, 第二个按钮都不能减少操作次数
如果r-l>1, 那么
x在l+2位置使用第二个按钮能够减少1次操作, 在l+3位置能减少2次… 在r位置能够减少r-(l+2)+1次操作
所以p[l+2] += 1, p[l+3] += 2 … p[r] += r-(l+2)+1
对每一对l, r如此处理, 得到最后的p数组
设all为只使用第一个按钮所需要的操作总次数
那么`最少操作次数 = all - max{p[i]+p[i+m]}, 1<=i<=m

#include <bits/stdc++.h>

using namespace std;

const int MAXN = 3E5 + 100;
typedef long long ll;
int n, m, a[MAXN];
ll p[MAXN];

int main()
{
    ll all = 0;
    scanf("%d%d", &n, &m);
    for(int i=0; i<n; ++i) scanf("%d", a+i);
    for(int i=1; i<n; ++i)
    {
        int l = a[i-1], r = a[i];
        if(l>r) r += m;
        all += r-l;
        if(r-l>1)
        {
            p[l+2] += 1;
            p[r+1] -= (r-(l+2)+1) + 1;
            p[r+2] += (r-(l+2)+1);
        }
    }
    for(int i=1; i<=2*m; ++i) p[i] += p[i-1];
    for(int i=1; i<=2*m; ++i) p[i] += p[i-1];

    ll ans = -1;
    for(int i=1; i<=m; ++i) ans = max(ans, p[i]+p[i+m]);
    cout << all - ans << endl;

    return 0;
}

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值