2021 年东华大学金马程序设计联赛

A. Smart AEMShana!

AEMShana isn’t just charming, he is also very smart.

While some of us were learning the addition table, AEMShana had fun in his own manner.
AEMShana painted an addition table, where the element on the intersection of the -th row and -th column equals (the rows and columns of the table are numbered starting from ).

Then he was asked: what number in the table is the -th least number? AEMShana always answered correctly and immediately. Can you repeat his success?

Consider the given addition table. If you write out all numbers from the table in the decreasing order, then the -th number you write out is called the -th leaest number.

Note

A addition table looks like this:

2 3 4
3 4 5
4 5 6

输入格式
There are multiple test cases(not more than ) in this problem.

In each test case contains integers and .

输出格式
Print the -th least number in a addition table.

样例
input
3 4
114514 1919810
output
4
1960
主要思路:
(签到题)
①:利用公式
②:二分

//公式
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdio>
using namespace std;
typedef long long ll;
int main()
{
    ll m,k;
    while(scanf("%lld%lld",&m,&k)!=EOF)
    {
        ll ans=0;
        if(k<=(1+m)*m/2)
        {
            ll n=ceil((sqrt(1+8*(double)k)-1)/2.0);
            ans=n+1;
        }
        else
        {
            k=m*m-k+1;
            ll n=ceil((sqrt(1+8*(double)k)-1)/2.0);//求数
            ans=2*m-n+1;
        }
        cout<<ans<<endl;
    }
    return 0;
}
//二分
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
int main()
{
	ll m,k;
	while(cin>>m>>k)
	{
		ll l=1,r=m;
		ll ans;
		if(k<=(1+m)*m/2)
		{
			while(l<r)
			{
				ll mid=(l+r)>>1;
				if((1+mid)*mid/2<k) l=mid+1;//>k一定不会是答案
				else r=mid;
			}
			ans=l+1;
		}
		else
		{
			k=m*m-k+1;
			while(l<r)
			{
				ll mid=(l+r)>>1;
				if((1+mid)*mid/2<k) l=mid+1;
				else r=mid;
			}
			ans=2*m-r+1;
		}
		cout<<ans<<endl;
	}
}

C. Back

There are villages and roads. If there is a road between two villages, they are directly reachable. If two villages are not directly reachable, they can first go to other directly reachable villages and then reach each other. We guarantee that there is at most one road between two villages, and each road is two-way, and any two villages can be reached. SDZ likes walking after dinner, but he doesn’t like to walk twice on the same road. He wondered whether there was a route, and he set off along this route, and eventually he could return to the starting point without the road being repeated.

输入格式
There are two numbers and in the first line, which means there are villages and roads.(

)

In the next line, each line has two numbers , and indicates that there is a road between village and village .

Note that there are multiple sets of inputs and the sum of is not more than and the sum of is not more than .

输出格式
If such a route can be found, output Yes, otherwise output No.

样例
input
1 1
1 1
output
Yes

主要思路:
判断是否存在自环,因为两村庄之间只有一条路,所以可以投机取巧,只要路数>=村数即存在自环
也可以用并查集模板
!!!可能不止一组

#include<iostream>
#include<algorithm>
#include<map>
using namespace std;
map<pair<int,int>,bool> book;
int main()
{
    int n,m;
    while(cin>>n>>m)
    {
        int nn=0;
        for(int i=0;i<m;i++)
        {
            int x,y;
            cin>>x>>y;
            if(!book[{x,y}])
            {
                nn++;
                book[{x,y}]=1;
            }
        }
        if(n<=nn)
            cout<<"Yes"<<endl;
        else cout<<"No"<<endl;
    }
    return 0;
}

D. Move the numbers

John has learned data structure and algorithm course this semester, and he has a problem in the latest problemset that he desperately needs your help.

Given a permutation of , and the position of the elements will be adjusted times.

Each adjustment specifies a index , which means to adjust the array with following operation:

First, append all numbers before the -th number to the end of the array in order.
And then, delete all numbers before the -th number.
Your task is to find the final permutation after operations.

输入格式
There are multiple test cases in this problem, and the input of each test case are as following statement:

In the first line of each test case, there are two integers and () , representing the number of elements in the array and the adjustment times correspondingly.

In the second line of each test case, there is a permutation of , representing the original permutation.

And in the last line of each test case, there are integers, representing the index of each adjustment.

It is guaranteed that the sum of over all test cases does not exceed , and the sum of over all test cases also does not exceed .

输出格式
For each test case, output one line which contains integers (separated by a space), representing the final permutation after operations.

样例
input
5 3
1 2 3 4 5
3 2 1
6 2
2 3 4 5 6 1
3 4
output
4 5 1 2 3
1 2 3 4 5 6

主要思路:
典型约瑟夫环问题,只要找到对头就可以,顺序是不会变的

#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e5+10;
int main()
{
    int n,m;
    while(cin>>n>>m)
    {
        int a[N];
        for(int i=0;i<n;i++)
            cin>>a[i];
        int op=0;
        while(m--)
        {
            int x;
            cin>>x;
            op+=x-1;
            op%=n;
        }
        int nn=n;
        while(nn--)
        {
            cout<<a[op]<<' ';
            op++;
            op%=n;
        }
        cout<<endl;
    }
    return 0;
}

H. A Simple Game

This quesiton is very simple.This quesiton is very simple.This quesiton is very simple.

Alice and Bob play a game. Initially they have cards. They take alternating turns, and Alice is moving first.

During each turn, the player will choose a certain card and get points. If Alice chooses the -th card, her score will be increased by . If Bob chooses the -th card,his score will be increased by . Each card can only be choosed by one player. The game ends when all cards are choosed.

Whoever gets a higher score, wins. You have to determine who wins if they both play optimally.

输入格式
There are multiple test cases in this problem.

In each test case,the first line contains one integer . The second line contains space-separated positive integers . The third line contains space-separated positive integers .

输出格式
For each test case print Alice if Alice can win and Bob if Bob can win.

If they get the same score,print AEMSHANA.

样例
input
3
1 2 3
4 5 6
2
1 8
9 1
2
3 5
4 1
output
Bob
AEMSHANA
Alice

主要思路:
主要是要考虑按什么排序
怎样能获得最大的价值呢?
自己的得分+对方得不到的分(即a[i]+b[i])

#include<iostream>
#include<algorithm>
#include<cstdio>
using namespace std;
const int N=1e5+1;
typedef long long ll;
typedef pair<ll,ll>pa;
bool cmp(pa a,pa b)
{
    return a.first>b.first;
}
int main()
{
    ll n;
    while(scanf("%lld",&n)!=EOF)
    {
        ll a[N],b[N];
        pa sum[N];
        for(int i=0;i<n;i++)
            scanf("%lld",&a[i]);
        for(int i=0;i<n;i++)
            scanf("%lld",&b[i]);
        for(int i=0;i<n;i++)
        {
            sum[i].first=a[i]+b[i];
            sum[i].second=i;
        }
        sort(sum,sum+n,cmp);
        ll suma=0,sumb=0;
        for(int i=0;i<n;i++)
        {
            if(i%2==0)
                suma+=a[sum[i].second];
            else sumb+=b[sum[i].second];
        }
        if(suma>sumb) cout<<"Alice"<<endl;
        else if(suma<sumb)cout<<"Bob"<<endl;
        else cout<<"AEMSHANA"<<endl;
    }
    return 0;
}

I. A Small Game

This is a simple question. This is a simple question.This is a simple question.

You are given four integers and .

Now you have a integer ( initially).

Each time you can choose one of the following operations:

Cost and gain ()
Cost and gain ()
Cost and gain ()
Find the minimun cost to get .

输入格式
There are multiple test cases in this problem.

In each test case,there is only one line contains four integers , , , .

输出格式
For each test case print one line for the minimun cost to get .

样例
input
1 0 0 0
10 1 10 1
10 1 0 10
10 10 0 1
output
0
10
2
12

主要思路:
利用一下贪心的思想,并且从逆序到0
首先分两种情况:单数(可加,可减),偶数(可减,可÷2)
注意记忆化搜索
为了防止因为+1出现自己调用自己的情况,book一下出现过的

#include<iostream>
#include<algorithm>
#include<cstring>
#include<map> 
using namespace std;
typedef long long ll;
map<ll,bool> book;
map<ll,ll> mp;
ll n,a,b,c;
ll dfs(int x)
{
	if(x<1||x>n+1) return 0;//防溢出 	
	if(mp[x]) return mp[x];//记忆化 
	if(book[x]) return 0x3f3f3f3f;//记忆化 
	book[x]=1;
	if(x%2==0) return mp[x]=min(x*a,dfs(x/2)+b);
	else return mp[x]=min(dfs(x-1)+a,dfs(x+1)+c);
}
int main()
{
	while(cin>>n>>a>>b>>c)
	{
		book.clear();
		mp.clear();
		cout<<dfs(n)<<endl;
	}
	return 0;
}

K. AEMShana loves games!

AEMShana loves playing video games.Recently he finds a Barrage game called Touhou Project.

Just like the picture above, AEMShana was born in the middle of a 10-meter-long street at time zero. AEMShana can only move one meter each second. Of course, he can stay where he is. For example, AEMShana can stay at 5 or move to 4 or 6 at the first second. And the sky will fall two kinds of balls. When you catch the balls you will get or lose points. If you are in the place where the ball is when it hits the ground, then you catch it (Whether you want to catch it or not). You will get one point when you catch the white ball while you will lose one point when you get the black ball. To break the game record,AEMShana hacked the games, So he knows when and where the black or white balls hit the ground. Can you help AEMShana calculate how much point can he get in this game? The point is zero at first and it can be negative(like -1).Remember that there may be many balls hit at the same time and place.
输入格式
There are multiple test cases in this problem.

In each test case, there is line, the first line contains an integer and each after lines contains integers which means the time when the balls hit the ground, the place where the balls hit the ground and the kind(‘0’ is white ball and ‘1’ is black ball) of the balls hited the ground.

输出格式
Print the highest point that AEMShana can get in this game.

样例
input
6
1 5 0
2 0 0
2 10 1
5 9 0
3 7 0
4 8 1
3
1 5 1
1 4 1
1 6 1
output
2
-1

主要思路:
因为只有0->10个点,数据极小
开始可能会想到贪心,但是根本没办法实现,局部最优和不是全局最优
既然不让人跟着球走,那就换一种思路,让人走
判断当前位置人的得分:
从左边来、从右边来、没动
于是,就可以写出状态转移方程了
dp[i][j]=max(dp[i-1][j-1],dp[i-1][j+1],dp[i-1][j])+book[i][j];
注意防止下标越界到-1,直接将0->10后移为1->11
另外要注意思考,从中点开始如何实现???
因为只能从5也就是移动后的6点开始,所以给dp[0][6]赋值为0,开始动态规划

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=1e5+8;        
int book[N][12],dp[N][12];
int main()
{
    int n;
    while(cin>>n)
    {
        memset(book,0,sizeof(book));
        memset(dp,0xf7,sizeof(dp));
        int ans=-1,maxt=-1;
        for(int i=0;i<n;i++)
        {
            int x,y,z;
            cin>>x>>y>>z;
            if(z==0)
                book[x][y+1]++;
            else if(z==1) book[x][y+1]--;
            maxt=max(maxt,x);
        }
        dp[0][6]=0;
        for(int i=1;i<=maxt;i++)
        {
            for(int j=1;j<=11;j++)
            {
                dp[i][j]=max(dp[i-1][j-1],max(dp[i-1][j+1],dp[i-1][j]))+book[i][j];
                ans=max(ans,dp[i][j]);
            }
        }
        cout<<ans<<endl;
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值