2020湖南大学程序设计竞赛新生赛部分题解(含AC代码)

竞赛地址:https://ac.nowcoder.com/acm/contest/3674#question
全部题解地址:https://ac.nowcoder.com/discuss/361704?type=101&order=0&pos=6&page=0

A.The GCD of Fibonacci Numbers(斐波那契数列性质)

题目大意:

给你两个数字m,n分别代表斐波那契数列的第m、n项,求这两个数的最大公约数。

解题思路:

本题用到了斐波那契数列的一个性质,gcd(Fn,Fm)=Fgcd(n,m) 以及斐波那契数列的通项公式:
在这里插入图片描述

AC代码:

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<set>
#include<string> 
#include<vector>
#include<stack>
#include<queue> 
#define PI 3.1415926
typedef long long ll;
using namespace std;
ll Q;
ll x,y,temp;
ll fib(ll n)
{
    const double d = sqrt(5);
    return floor((pow((1+d)/2, n) - pow((1-d)/2, n))/d + 0.5);
} 
ll Euclid_GCD(ll a, ll b)
{     
 	return b?Euclid_GCD(b, a%b):a;
}
	int main()
	{
		ll t=0;
		cin>>t;
		while(t--)
	{
		ll a=0,b=0;
		cin>>a>>b;
		Q=Euclid_GCD(a,b);
		cout<<fib(Q)<<endl;
	}
	return 0;
}

斐波那契数列其余性质(来自百度)

在这里插入图片描述

F.Kuangyeye’s Game(几何+思维)

题目大意:

给你几个点的坐标(x,y),请判断他们是不是在一条直线上,注意,几个点中可能有重复的,也就是说可能存在连续多个坐标相同的点。

题目分析:

在同一条直线上的点他们的斜率相同,也就是说y的差值比上x的差值相同。但是要注意一点,当连续几个点的坐标相同时,不能直接算x,y的差值,因为0不能做除数。

AC代码:

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<set>
#include<string> 
#include<vector>
#include<stack>
#include<queue> 
#define PI 3.1415926
typedef long long ll;
using namespace std;
int main()
{
	int n=0;
	static int x[1010]={0};
	static int y[1010]={0};
	cin>>n;
	for(int i=0;i<n;i++)
	{
		scanf("%d%d",&x[i],&y[i]);
	}
	for(int i=0;i<n-2;i++)
	{
		if(x[i]!=x[i+1]&&y[i]!=y[i+1]&&x[i+1]!=x[i+2]&&y[i+1]!=y[i+2])
		//不存在连续的坐标相同的点
		{
			if((double)(y[i]-y[i+1])/(double)(x[i]-x[i+1])!=(double)(y[i+1]-y[i+2])/(double)(x[i+1]-x[i+2]))
			{
				cout<<"No"<<endl;
				return 0;
			}
		}
		else
		continue;
	}
	cout<<"Yes"<<endl;
	return 0;
}

G.Buying Keys(思维+贪心)

题目大意:

钥匙三块钱一把,十块钱三把,小明有一定数量的钱,问怎么样在把钱花完的前提下配最少数量的钥匙,如果钱无论如何都花不完,输出orz;

题目分析:

就是一个贪心的思想,先紧着十块钱三把的方式配。如果小明的钱不是10的整倍数,那么就三块一把这样配,直到小明的钱小于3或者成为10的倍数,如果小明剩余的钱不为0,那么输出orz。

AC代码:

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<set>
#include<string> 
#include<vector>
#include<stack>
#include<queue> 
#define PI 3.1415926
typedef long long ll;
using namespace std;
int main()
{
	ll n=0,N=0,t=0;
	cin>>n;
	N=n;
	if(n%10==0)
	{
		n/=10;
		n*=3;
		cout<<n<<endl;
		return 0;
	}
	else
	{
		while(n%10!=0&&n>=3)
		{
			n-=3;
			t++;
		}
		if(n%10==0)
		{
			n=n/10*3+t;
			cout<<n<<endl;
			return 0;
		}
		if(n<3&&n!=0)
		{
			cout<<"orz"<<endl;
			return 0;
		}
		if(n==0)
		{
			cout<<t<<endl;
			return 0;
			}	
	}
}

H.Dice(概率+思维)

题目大意:

摇n轮骰子,每一次摇骰子你获胜的概率都是50%,第一轮你下的注为1,如果第一局你输了,那么下一次你下的注就是上一轮的两倍。如果你赢了,你就见好就收,结束游戏。问你赢钱的概率是多大。

题目分析:

如果你摇n次骰子,则每一轮下的注的值为2^(n-1),(即1,2,4,8……),由此可见,你只要赢一次,你就能赢钱(因为你懂的见好就收)。因此,咱们要算的是你这n局中每一局都输的概率,再用1减去这个概率就好,注意保留四位小数。而每一局都输的概率为0.5 ^ n。

AC代码:

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<set>
#include<string> 
#include<vector>
#include<stack>
#include<queue> 
#define PI 3.1415926
typedef long long ll;
using namespace std;
int main()
{
	int t=0;
	cin>>t;
	double ans;
	while(t--)
	{
		ans=0;
		int n=0;
		cin>>n;
		//n++;
		while(n>=1)
		{
			ans+=pow(0.5,n);
			n--;
		}
		printf("%.4lf\n",ans);
	}
	return 0;
}

J.Fake Nim(思维)

题目描述:

有n堆糖果,每一堆都有各自的数量,DaDa一次能买一堆糖中的偶数个,TuTu一次能买一堆糖中的奇数个,如果商店中的每一堆糖果的个数都小于2,则DaDa就无法购买。谁买走商店中的最后一颗糖谁就获胜,现在DaDa先去买,问谁最后能获胜?

题目分析:

如果一堆糖有k个,假如k是偶数,则TuTu可以买k-1个糖,使得这一堆只剩下1个糖,从而造成DaDa无法再买这一堆糖;假如k是奇数,则TuTu可以把它们全部买走。由上述分析可知,因为DaDa是先手,所以当只有一堆糖且这一堆糖的个数为偶数时DaDa获胜,其余情况均是TuTu获胜。

AC代码:

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<set>
#include<string> 
#include<vector>
#include<stack>
#include<queue> 
#define PI 3.1415926
typedef long long ll;
using namespace std;
int main()
{
	int n=0;
	cin>>n;
	static ll a[50010]={0};
	for(int i=0;i<n;i++)
	{
		scanf("%lld",&a[i]);
	}
	if(n==1&&a[0]%2==0)
	cout<<"DaDa"<<endl;
	else
	cout<<"TuTu"<<endl;
	return 0;
}

L.Special number(质数判断+特殊情况)

题目大意:

给你一个闭区间的两个端点,问在这个闭区间内有多少个因数不超过3个数的数。

题目分析:

因数不超过3个,则其因数一定为1个或者2个。质数只有两个因数(1和它本身),1只有一个因数1。所以本题要做的就是判断这个区间内有多少个质数,如果区间里面有1,则1也算进去。注意一点,0这个数比较特殊,它没有因数,所以不算题目中所描述的Special number。

AC代码:

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<set>
#include<string> 
#include<vector>
#include<stack>
#include<queue> 
#define PI 3.1415926
typedef long long ll;
using namespace std;
int main(){
    ll m;  
    ll i;  
    ll k;  
    ll l=0,r=0,ans=0;
    static ll a[100010]={0};
    cin>>l>>r;
    for(ll i=l;i<=r;i++)
    a[i]=i;
    for(ll j=l;j<=r;j++)
    {
    	k=(ll)sqrt( (double)a[j] );
    	for(i=2;i<=k;i++)
        if(a[j]%i==0)
        break;
    	if(i>k&&a[j]!=0)//所有质数还有1,0不算,因为0不能做除数
        ans++;
	}
    cout<<ans<<endl;
    return 0;
}

M.XOR sum(异或的应用)

题目大意:

给你一个闭区间的左右端点,请你求一下这个闭区间内所有数字相异或的值。

题目分析:

目前不太理解,日后补。如果有大佬有好的见解,欢迎提出。

经过GX大佬的指点好像明白了点。数字的异或有一个规律,从0开始,每四个数字的异或结果为0。而代码中也正是利用了这个规律,进而可以求出任意给定闭区间【A,B】中各项数字的异或。

AC代码:

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<set>
#include<string> 
#include<vector>
#include<stack>
#include<queue> 
#define PI 3.1415926
typedef long long ll;
using namespace std;
int main() {
	long long A,B;
	cin >> A >> B;
	long long a=4-A%4, b=B%4, n=0;
	for(long long i=A;   i<A+a; i++) n=n^i;
	for(long long i=B-b; i<=B;  i++) n=n^i;
	cout << n << endl;
	return 0;
}  
  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值