2020牛客寒假算法基础集训营5 (立方根、博弈规律、组合数学+dp、字符串26进制数、并列第三、简单几何)

链接:https://ac.nowcoder.com/acm/contest/3006/D
来源:牛客网
 

牛牛与牛妹的约会  ->贪心+立方根

时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 262144K,其他语言524288K
Special Judge, 64bit IO Format: %lld

题目描述

牛牛在辛苦的一天的比赛之后,要去找牛妹玩,其实牛妹那天也在比赛。他为了找到牛妹,要尽快的从自己的比赛地到她的比赛地。

还记得吗,比赛地都是只在xxx轴上的,所以两个人的坐标都满足y=0y=0y=0。牛牛除了可以以111单位距离/单位时间的速度移动任意时间以外,还可以花费111单位时间进行闪现。每次闪现时,如果当前他的坐标是x=kx=kx=k,他将闪现到x=k3x=\sqrt[3]{k}x=3k​的位置。

请帮他算算,最短需要多少时间,他可以找到牛妹~

输入描述:

 

输入数据包括多组用例,输入第一行包含一个数字T(1≤T≤5×105)T(1 \leq T \leq 5 \times 10^5)T(1≤T≤5×105),表示数据组数。

接下来TTT行,每行包括两个整数a,b(∣a∣,∣b∣≤106)a,b(|a|,|b|\leq 10^6)a,b(∣a∣,∣b∣≤106),表示牛牛所在的位置和牛妹所在的位置。

输出描述:

 

输出共TTT行,每行包括一个实数,表示牛牛所花费的最短时间。

如果你的答案是aaa,标准答案是bbb,当∣a−b∣≤10−6|a-b|\leq 10^{-6}∣a−b∣≤10−6时,你的答案将被判定为正确。

示例1

输入

复制2 3 -1 1 2

2
3 -1
1 2

输出

复制3.442249570 1.000000000

3.442249570
1.000000000

#include<bits/stdc++.h>
using namespace std;
int n;
double  a,b;
double f(double  x)
{
	if(x<0)
	{
		return -1*pow(-1*x,1.0/3.0);
	}
	else
	{	
	 return pow(x,1.0/3.0);
	}
}
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		scanf("%lf%lf",&a,&b);// %lf !!!
		double ans=0;
		if(a*b<0)
		{
			double next=f(a);
			
			do{				
				if(abs(a-next)>=1) 
				{
					ans+=1;
					a=next;
				}
				next=f(a);
			}while(abs(a-next)>=1);
			ans+=abs(a-b);
			printf("%.9f\n",ans);
		}
		else 
		{
			double next=f(a);
			
			do{				
				if(abs(a-next)>=1&&abs(next-b)+1<=abs(a-b)) 
				{
					ans+=1;
					a=next;
				}
				next=f(a);
			}while(abs(a-next)>=1&&abs(next-b)+1<=abs(a-b));
			ans+=abs(a-b);
			printf("%.9f\n",ans);
		}
	}
}

链接:https://ac.nowcoder.com/acm/contest/3006/E
来源:牛客网
 

Enjoy the game   博弈 规律题  

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

牛牛战队的三个队员在训练之余会自己口胡了一些题当做平时的益智游戏。有一天牛可乐想出了一个小游戏给另外两名队员玩,游戏规则如下:

  • 初始一共有nnn张卡牌
  • 先手第一步最少要拿111张牌,最多要拿n−1n-1n−1张牌。
  • 接下来每一步,双方最少要拿111张牌,最多拿等同于上一步对方拿的牌数的牌。
  • 拿走最后一张牌的人将取得游戏的胜利。

你作为旁观者,看着他们玩的很开心,想参与到这场游戏中来,赌一赌谁会能赢。

输入描述:

输入数据包含一个整数nnn(2≤n≤10182 \leq n \leq 10^{18}2≤n≤1018),表示初始卡牌张数。

输出描述:

如果先手有必胜策略,输出Bob,否则输出Alice。

示例1

输入

复制2

2

输出

复制Alice

Alice

说明

先手必须拿走一张牌,然后后手拿走了另一张牌,游戏结束。

解法:2^n 是 Alice赢  其它为Bob赢

#include<bits/stdc++.h>
using namespace std;
long long  n;
char s[100];
int main()
{
	scanf("%lld",&n);	
	int flag=0;
	if(n%2)
	{
		printf("Bob\n");
		return 0;
	}
	
	while(n)
	{
		if(n%2)
		{
			if(n==1) break;
			else 
			{
				flag=1;
				break;
			}
		}
		n/=2;
	}
	
	if(flag)
	{
		printf("Bob\n");
	}
	else printf("Alice\n");
}

链接:https://ac.nowcoder.com/acm/contest/3006/F
来源:牛客网
 

碎碎念    组合数学+dp

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

在ACM比赛里,除了CE以外都是有效的提交。每一个提交都会有其评测的结果,或是AC,或是RJ(Rejected,包含各种不通过的情况)。往往一个人上去提交的时候,总有一个队友会坐在边上等着结果。那个人,往往都是只读题不写题的云选手~

牛牛战队里也有这样的云选手——牛能。当牛能看到有效提交得到了AC以后,都会大呼一声“你好能啊!”,反之,如果得到了RJ的话,就会化身为喷子,说xxx句“你能不能行啊!”。大家比赛的都十分紧张,这样的大声呼喊未免会引起旁边队伍的注意。

当然牛牛战队交题的时候也很小心,一旦这一发出现了RJ,下一发有效提交一定能获得AC。

比赛结束了以后,旁边的一支队伍愤怒的跑过来说:你们比赛的时候吵不吵啊,一直在这大吼,吼了这么多句!

激烈的争吵引起了吃瓜群众的注意,吃瓜群众问道:吼了多少句啊,这么讨厌的吗

“啊……我也记不清了,大概是在[L,R][L,R][L,R]这个区间吧”

作为吃瓜群众的你,想根据这个信息算出,这个队伍有多少种有效提交结果序列的可能呢?

输入描述:

 

输入数据包括单组数据、多组询问。输入第一行包含一个整数x(2≤x≤100 000)x(2 \leq x \leq 100\,000)x(2≤x≤100000),表示牛能在RJ状态下会说“你能不能行啊!”的句子数量。

第二行包括一个整数Q(1≤Q≤105)Q(1 \leq Q \leq 10^5)Q(1≤Q≤105),表示询问数量。

接下来QQQ行,每行包括两个整数L,R(1≤L≤R≤100 000)L,R(1 \leq L \leq R \leq 100\,000)L,R(1≤L≤R≤100000),表示每次询问下句子的区间数。

输出描述:

对于每组数据,在一行内输出一个整数,表示牛牛战队提交结果的可能性。由于结果可能很大,请对1 000 000 0071\,000\,000\,0071000000007取模。

示例1

输入

复制3 3 3 3 1 4 1 5

3
3
3 3
1 4
1 5

输出

复制2 7 11

2
7
11

说明

 

第一组询问:可以是三个AC,或者一个RJ。

第二组询问:可以是1~4个AC,一个AC和一个RJ(共2种顺序),或者一个RJ。

第三组询问:可以有1~5个AC,两个AC和一个RJ(共3种顺序),一个AC和一个RJ(共2种顺序),或者一个RJ。

备注:

AC RJ AC AC 和 AC AC AC RJ 虽然都是3个AC,1个RJ,但是因为提交顺序的不同,视为不同种类。

解法:n个AC,m个RJ 的组合数为 C(n+1,m)

预处理[1,1e6或1e5]的阶乘和逆元,O(1) 计算C(n+1,m)

记录所有询问中最大的R为maxx,然后枚举[1,maxx] 的所有(n,m) 的组合情况,即m的范围在[0,maxx / (x+1) ]

每算一个C(n+1,m),记录它的贡献dp[m*x+n] +=C(n+1,m) ,

然后dp[i]函数前缀和,每次询问时,答案即为  R-L+1+dp[R] -dp[L-1] ;

#include<bits/stdc++.h> 
#define ll long long
#define mod 1000000007
using namespace std;
ll A[1000006],inv[1000006];
ll quick_mi(ll x,ll y)//快速幂求逆元  inv 
{
	ll res=1;
	while(y)
	{
		if(y&1) res=res*x%mod;//!!!res取模啊!!! 
		x*=x;
		x%=mod;
		y>>=1;
	}
	return res;	
}
 
ll C(ll n,ll m)//组合数 
{
    ll ans=A[n]*inv[m] % mod*inv[n-m] % mod;
    return ans;
}
int x;
ll dp[100005];
struct node
{
	int l,r;
}N[100005];
int main()
{
	
	A[0]=1; //!!! 
	inv[0]=1;//!!! 特殊处理 
	for(int i=1;i<=1000000;i++)//阶乘预处理范围 
	{
		A[i]=A[i-1]*i%mod;//排列数  阶乘 
		inv[i]=quick_mi(A[i],mod-2);
	}
	scanf("%d",&x);
	int Q;
	scanf("%d",&Q);
	int maxx=0;
	for(int i=1;i<=Q;i++)
	{
		scanf("%d%d",&N[i].l,&N[i].r);
		maxx=max(maxx,N[i].r);
	}
	for(int i=1;i<=maxx/(x+1);i++)
	{
		long long num;
		for(int j=i-1;i*x+j<=maxx;j++)
		{
			if(j==i-1)
			{
				num=C(j+1,i);
			}
			else 
			{
				num=C(j+1,i);
			} 
				dp[i*x+j]=dp[i*x+j]+num;
				dp[i*x+j]%=mod;
		}
	}
	for(int i=1;i<=maxx;i++)
	{
		dp[i]+=dp[i-1];
		dp[i]%=mod;
	}
	for(int i=1;i<=Q;i++)
	{
		ll ans=N[i].r-N[i].l+1+dp[N[i].r] -dp[N[i].l-1]+mod;
		ans%=mod;
		printf("%lld\n",ans);
	}
	
	
}

链接:https://ac.nowcoder.com/acm/contest/3006/H
来源:牛客网
 

Hash    模拟

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

这里有一个hash函数

const int LEN = 6;
int mod;
int Hash(char str[])
{
    int res = 0;
    for (int i = 0; i < LEN; i++)
    {
        res = (res * 26 + str[i] - 'a') % mod; 
    }
    return res;
}

现给定一个长度为666的仅由小写字母构成的字符串sss和模数modmodmod,请找到字典序最小且大于sss的一个长度为666的仅由小写字母构成的字符串s′s's′,使得其hash值和sss的hash相等。

输入描述:

 

多组用例,请处理到文件结束。(用例组数大约为1000组左右)

对于每组用例,输入一行,包含一个长度为666的仅由小写字母构成的字符串sss和模数mod(2≤mod≤107)mod(2 \leq mod \leq 10^7)mod(2≤mod≤107),用空格隔开。

输出描述:

对于每组用例,如果存在如题目所述的s′s's′,请输出s′s's′,否则输出-1。

示例1

输入

复制abcdef 11

abcdef 11

输出

复制abcdeq

abcdeq

解法:模拟26进制数,然后+mod,再转回 字符串

#include<bits/stdc++.h>
#define ll long long
using namespace std;
char s[10];
const int LEN = 6;
int mod;
int Hash(char str[])
{
    int res = 0;
    for (int i = 0; i < LEN; i++)
    {
        res = (res * 26 + str[i] - 'a') % mod;
    }
    return res;
}
int num[10];
ll sum[10];
int ans[10];
int main()
{
    while(cin>>s>>mod)
    {
    	
	
 
    int hh=1;
     
    int mini=5;
    num[5]=1;
    for(int i=4;i>=0;i--)
    {
        num[i]=num[i+1]*26%mod;
    }
     
    ll summ=0;
    for(int i=5;i>=0;i--)
    {
        mini=i;
        sum[i]=('z'-s[i])*num[i];
        summ+=sum[i];
        if(summ>=mod) break;
    }
    if(summ>=mod) mod=summ-mod;
    else
    {
        printf("-1\n");
        return 0;
    }
     
     
    for(int i=mini;mod&&i<=5;i++)
    {
        ans[i]=min('z'-s[i],mod/num[i]);
        mod-=ans[i]*num[i];
             
    }
        if(mod)
        {
            printf("-1\n");
            continue;;
        }
         
        for(int i=0;i<=5;i++)
        {
            if(ans[i])
            {
                printf("%c",'z'-ans[i]);
            }
            else printf("%c",s[i]);
        }
 }
     
     
     
     
     
}

链接:https://ac.nowcoder.com/acm/contest/3006/I
来源:牛客网
 

I题是个签到题 

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
Special Judge, 64bit IO Format: %lld

题目描述

经过2019一年的比赛,牛牛战队的队员发现了一个重大规律:I题是个签到题!

签到题的定义是:通过人数大于等于全场人数的80%80\%80%或者通过人数是所有题目前三多的题(也就是最多有两个题目通过人数严格比它多)叫做签到题。

2020赛季就要到了,牛牛战队要去验证这个规律了,已知现在每个题的过题情况,看一看I题是不是一个签到题。

输入描述:

 

输入数据共222行。第一行包括两个整数n,m(9≤n≤13,100≤m≤1 000)n,m(9 \leq n \leq 13, 100 \leq m \leq 1\,000)n,m(9≤n≤13,100≤m≤1000),表示比赛的总题数和比赛的总人数。

第二行包括以空格分隔的nnn个整数a1,a2,⋯ ,an(ai>0)a_1,a_2,\cdots,a_n(a_i > 0)a1​,a2​,⋯,an​(ai​>0),表示每个题通过的人数。

输出描述:

如果I题是个签到题,则输出Yes,否则输出No。(不区分大小写)

示例1

输入

复制9 100 100 100 100 100 100 100 100 100 100

9 100
100 100 100 100 100 100 100 100 100

输出

复制Yes

Yes

并列第三的概念。。。xiuchi。。。

3 3 2 2 1 1  两个并列第一 、两个并列第三、两个并列第五

3 3 3 3 2 2 四个并列第一、两个并列第五

3 2 2 2 1 1 三个并列第二、两个并列第五

应该是这样。。。maybe。。。

#include<bits/stdc++.h>
using namespace std;
int n;
double m;
int a[20];
bool cmp(int a, int b)
{
	return a>b;
}
int main()
{
	cin>>n>>m;
	
	double hh;
	for(int i=0;i<n;i++)
	{
		cin>>a[i];		
		if(i==8) hh=a[i];
	}
	if(0.8*m<=hh)
	{
		printf("Yes\n");
		return 0;
	}
	
	sort(a,a+n,cmp);	
	if(hh>=a[2])
	{
		printf("Yes\n");
	}
	else printf("No\n");
	
}

链接:https://ac.nowcoder.com/acm/contest/3006/J
来源:牛客网
 

牛牛战队的秀场   简单几何

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
Special Judge, 64bit IO Format: %lld

题目描述

牛牛战队里,不仅有训练,也有追逐。

牛牛和牛能总是想知道谁更秀一点,他们通常会去比谁的代码更秀,谁的成绩更秀……

这一次,他们开始比谁的走位更秀。他们来到一个半径为rrr的圆上,画了圆内接的正nnn边形。为了秀走位,他们只允许自己在多边形的边上移动。

同时,他们随便选取正nnn边形的一个顶点为1号顶点,按顺时针的顺序把其他的点叫做2号顶点,3号顶点……一开始,两人分别在iii号顶点和jjj号顶点。

现在,牛牛要一边沿着多边形的边秀走位,一边走向牛能。他想知道,他最短要走多少距离才能走到牛能的旁边?

输入描述:

 

输入数据共222行,第一行有两个整数nnn,rrr(3≤n≤1000,1≤r≤1063 \leq n \leq 1000, 1 \leq r \leq 10^63≤n≤1000,1≤r≤106),表示在半径为rrr的圆上画了一个内接nnn边形。

第二行有两个整数i,j(1≤i,j≤n)i, j(1 \leq i, j \leq n)i,j(1≤i,j≤n),表示牛牛一开始在iii号顶点,牛能一开始在jjj号顶点。

输出描述:

 

一个小数xxx,表示牛牛要移动的最短距离。

如果你的答案是aaa,标准答案是bbb,如果∣a−b∣max(1,∣b∣)≤10−6 \frac{|a-b|}{max(1,|b|)}\leq 10^{-6} max(1,∣b∣)∣a−b∣​≤10−6,你的答案将被判定为正确。

示例1

输入

复制4 1 1 2

4 1
1 2

输出

复制1.414214

1.414214
#include<bits/stdc++.h>
#define pi acos(-1)
using namespace std;
int n;
long long r;
int ii,jj;
int main()
{
	scanf("%d%lld",&n,&r);
	scanf("%d%d",&ii,&jj);
	int ans=min(abs(jj-ii),n-abs(jj-ii));
	double l=sqrt(r*r*2-2*r*r*cos(2*pi/n));
	printf("%.6f\n",ans*l);
}
发布了54 篇原创文章 · 获赞 7 · 访问量 3437

猜你喜欢

转载自blog.csdn.net/qq_43868883/article/details/104318591