2020年2月2日山师训练赛4

目录

  • H - Triangle
  • I - Birthday Paradox
  • K - Reverse a Substring
  • L - Game with Telephone Numbers
  • M - Alarm Clocks Everywhere

H - Triangle

题意:给你一个数n,从1~n,让你挑出来最少的数,来使之后的这些数无法构成三角形。

解法:我们由三角形存在定理,可以联想到斐波那契数列,其中的数,是由前两个数加和而来的,然后再写几个找规律,观察到结果即为n减去不大于n的 Fibonacci number 的个数

代码:

#include
#include
using namespace std;
int a[9]={1,1,2,3,5,8,13,21};
using namespace std;
int main()
{
	int t,sum,index,y=1;
	cin>>t;
	while(t--)
	{
		int n,index,k=0;
		cin>>n;
		printf("Case #%d: ",y);
		if(n<=3)
		{
			cout<<0<<endl;
		 }
		 else
		 {
		index=1;
		while(n>=a[index])
		{
		 k++;
		 index++;
		}
		cout<<n-k<<endl;
		
	}
		y++;
		
		
	}
	
}

I - Birthday Paradox

题意:一年有n天,让你找出参加聚会的最小人数,这样至少有两个人过同一个生日的概率至少是0.5。

解法:这是一个数学题,解法见度娘生日悖论解法

代码:

#include
#include
using namespace std;
int main()
{
	int t,w=1;
	cin>>t;
	while(t--)
	{
		int sum=1,n;
		cin>>n;
		double x=1.0;
		while(1-x<0.5)
		{
			
			x*=(1-sum*1.0/n);
			sum++;
		}
	printf("Case %d: %d\n",w,sum-1);
	w++;
		
	}
	
	
}

K - Reverse a Substring

题意:给你一串字符串,问你能不能找到它的一个连续子串,使得反转之后它的字典序比原来的小

解法:水题,我以为要按照题目给的例子来呢,想了半天,原来只要有一个符合就行

代码:

#include
#include
using namespace std;
int main()
{   int n;
	cin>>n;
	string w;
	int i,k;
	cin>>w;
	for(i=0;i<w.length()-1;i++)//必须到w.length()-2,如果到w.length()-1,i+1的位置会没有字符,比出来错的 
	{
		if(w[i]>w[i+1])
		{
		    k=i;
			break;
		}
		
	}
	if(i<w.length()-1)
	{  cout<<"YES"<<endl;
	cout<<k+1<<' '<<k+2<<endl;
}
	else
	cout<<"NO"<<endl;
	
	
 } 

L - Game with Telephone Numbers

题意:有一个字符串,有a,b两个人,a先手,b后手,每个人可以每次删掉任意位置的一个字符,最终当字符串的个数为11并且开头为8时则a获胜,反之则b获胜

解法:这个题比赛没想出来,之后问的王dalao,我们可以贪心考虑,为了获得胜利:b:尽量删掉靠前的’8’字符,a:尽量删掉靠前的非’8’字符,最终字符串的长度一定会变为11,那么每个人就会操作((n-11)/2)次,由于字符从0开始,我们就看前((n-11)/2)-1次就行,还有种情况得特判

代码:

#include
#include
using namespace std;
int main(){
	int n;
	char a[100005];
	cin>>n;
	cin>>a;
	int b=(n-11)/2;
	int num=0; 
	int flag =0;
	for(int i=0;i<=2*b-1;i++){//字符串从0开始所以到2*b-1 
		if(a[i]=='8') num++;
	}                                                //012 
	if(a[2*b]=='8') flag=1;//特判的一种情就是长度为(1)13  8380011223344,那么每人都操作一次 b=(n-11)/2,那操作的就看前2*b个字符串就行了 
	if(num<b) cout<<"NO";                    //这里第一个可以删第0位的8,第二个怎么删最后也是八开头的 
	else if(num==b&&flag==0) cout<<"NO";    //(2)若换为13  8330011223344 ,第一个比如删第一位的3,那么第二个人就可以删第0位的八,最后就不是八开头了 
	else cout<<"YES";                       //所以如果 num==b&&flag==0就是上面的情况,就输了
	                                          //若为(1)就是a[2*b]=‘8’它就赢了 
}

M - Alarm Clocks Everywhere

题意:有一个因为第二天有好多事,让你帮忙设计订闹钟,你可以选择任意时间为闹铃响的第一分钟设为y,但你不能随便选闹铃响的间隔,得从给的数据选设为p,选完之后闹铃响起为y,y+p,…,第 i个活动将在 xi 分钟开始,你要保证选完了,闹钟的响铃时间包含x1,x2,…,xn,闹钟可以在没有活动时响起

解法:找每一件事间隔时间的最大公因数,分情况模拟即可

我写的麻烦代码:

#include
#include
using namespace std;
typedef long long  ll;
const int maxn=3e5+10;
ll n,m,x[maxn],p[maxn],k,flag=0,a[maxn],w=0;
ll gcd(ll a,ll b)
{
	return !b?a:gcd(b,a%b);
}
int main()
{
	
	cin>>n>>m;
	for(int i=1;i<=n;i++)
	{
	cin>>x[i];

}
 for(int i = 1; i < n; i++)
        a[i] = x[i+1]-x[i];

	for(int i=1;i<=m;i++)
	{
	cin>>p[i];
	if(p[i]==1)
	flag=i;
}
    k=a[1];
		for(int i=2;i<n;i++)
	{
       
       k=gcd(a[i],k);
}
	   if(k==1&&flag)
	   {
	   	cout<<"YES"<<endl;
	   	cout<<x[1]<<' '<<flag;
	   }
	   else if(k!=1)
	   {
	   	for(int i=1;i<=m;i++)
	   	{
	   		if(k%p[i]==0)//注意必须是k%p[i]不可以反过来写,因为间隔的最大时间就是K,如果k=3,p[i]=6,选6是不可以的,有的大事发生时不会响起闹铃 
	   		{
	   		w=i;
	   		break;
	   	}
		   }
		   if(w)
		   { 
		   	cout<<"YES"<<endl;
	   	cout<<x[1]<<' '<<w;
	   }
	   else
	   cout<<"NO"<<endl;
}
	   else 
	   cout<<"NO"<<endl;
	
	
 } 

dalao的简便代码:

#include 
#include 
using namespace std;
#define ms(x, n) memset(x,n,sizeof(x));
typedef  long long LL;
const LL maxn = 3*1e5+10;

int n, m;
LL x[maxn], p[maxn], a[maxn];
LL gcd(LL a,LL b){ a=abs(a); b=abs(b); return a==0?b:gcd(b%a,a); }
int main()
{
    cin >> n >> m;
    for(int i = 1; i <= n; i++)
        cin >> x[i];
    for(int i = 1; i <= m; i++)
        cin >> p[i];

    for(int i = 1; i < n; i++)
        a[i] = x[i+1]-x[i];

    LL tag = a[1];
    for(int i = 2; i < n; i++)
        tag = gcd(tag, a[i]);
    for(int i = 1; i <= m; i++)
        if(tag%p[i]==0){
            cout << "YES" << endl<< x[1] << " " << i << endl;
            return 0;
        }
    cout << "NO" << endl;

	return 0;
}

你可能感兴趣的:(2020年2月2日山师训练赛4)