牛客比赛0206题解

A-做游戏

题意

两个人在石头剪刀布,知道两个人 出了 石头剪刀布的次数
求第一个人最多能赢多少次

思路

就是min(石头1,剪刀2)+min(布1,石头2)+min(剪刀1,布2)

代码

#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
	long long a1,a2,a3;
	long long b1,b2,b3;
	cin>>a1>>a2>>a3>>b1>>b2>>b3;
	long long sum=0;
	sum+=min(a1,b2)+min(a2,b3)+min(a3,b1);
	cout<<sum<<endl;
}

B-排数字

题意

牛可乐得到了一个纯数字的字符串 \text{}SS,他想知道在可以任意打乱 \text{}SS 顺序的情况下,最多有多少个不同的子串为 \text{616}616 。

思路

统计1和6的个数
当 因为可以使 61616
一个6可以当两边用
如果 6大于1 那么数量就是1的 数量
如果 6等于1 6161 数量是1 的个数减1
如果6小于1 61611 6161611数量是6的个数减1

代码

#include<string>
using namespace std;
int main()
{
	int n;
	string s;
	cin>>n>>s;
	int sum6=0;
	int sum1=0;
	for(int i=0;i<n;i++)
	 {
	 	if(s[i]=='1')
	 	 sum1++;
	 	if(s[i]=='6')
	 	 sum6++;
	 }
	int ans;
	if(sum1<sum6)
	 ans=sum1;
	else
	 {
	 	if(sum1==sum6)
	 	 ans=sum1-1;
	 	else
	 	 ans=sum6-1;
	 }
	cout<<ans<<endl;
	return 0;
}

C-算概率

题意

给你n道题目,知道每道题目正确的概率,第i道为p[i,分别求出n道题目里分别有0,1,2,3,n道题目做对的概率

思路

用一个二维数组f[i][j]表示i道题里有j道题做对的概率,要知道f[i][j]得知道f[i]
[0],求f[i][0]表示i 道题做对0道也就是 全做错了,就是前i-1道题做错的概率再乘以第i道题做错的概率 也就是f【i-1】[o](1-p[i]),然后再求i道题里面做对j道题的概率,方法是:分成两种情况分别是第i道题做没做对,即f【i】【j】=f[i-1][j](1-p[i])+f[i][j-1]p[i]
该式的意义是第i题做错的概率。为了方便计算,我们都是假设分式a/b当中分母b的值为1,即b=1,(因为任何分式都可以化为分母为1的式子,当然,分子a可以为小数。所以由b
q%(1e9+7)=a;这里b=1,q就是我们输入的p[i],可得p[i]=kmod+a;即a=p[i]-kmod;那么求对应的错误的概率就是用1-a,即1-a=(kmod+1-p[i])%mod=(mod+1-p[i])%mod,因为分母b为1;

代码

#include<iostream>
const int mod=1e9+7;
long long p[2020],f[2020][2020];
using namespace std;
int main()
{
	int n;
	cin>>n; 
	for(int i=1;i<=n;i++)//(mod+1-p[i])%mod 为做错的概率 
	 cin>>p[i];
	f[0][0]=1;//0道题目做对0道的概率肯定是1;
	for(int i=1;i<=n;i++) 
	 {f[i][0]=f[i-1][0]*(mod+1-p[i])%mod;//求i道题目做对0道的概率
	  //也就是全做错的gai概率就是前i-1道全做错再乘第i道做错的概率
	  for(int j=1;j<=i;j++) 
	    f[i][j]=(f[i-1][j]*(mod+1-p[i])%mod+f[i-1][j-1]*p[i])%mod;
	   //求i道题目作对j道的概率分两种情况一种是第i道没做对,就是
	   //前i-1道做对j道的概率再乘以第i道,没做对的概率
	   //还有一种情况就是第j道做对了概率就是 前i-1 道做对j-1道的概率再乘以第i道做对的概率
	 } 
	  for(int i=0;i<=n;i++){
        cout<<f[n][i];
        if(i<n)  cout<<" "; //为了按题目格式输出,希望这个方法还没学到的同学可以记住
    }
    return 0;
}
	   

D.数三角

题意

给你n个点,给出他们的坐标,问能够构成多少个钝角三角形

思路

利用向量,两个向量的乘积如果小于0那么他们的夹角就大于90度但要注意共线的情况,暴力枚举三个点,分别求这个三个点的角只要有一个是钝角那么就是钝角三角形

代码

#include<iostream>
using namespace std;
int x[510],y[510];
bool juge(int a,int b,int c) 
{
	int res1=x[b]-x[a];
	int res2=y[b]-y[a];
	int res3=x[c]-x[a];
	int res4=y[c]-y[a];
	if(res1*res3+res2*res4<0&&res1*res4!=res3*res2)
	 return true;
	return false;
}//对于两个向量(a1,b1)(a2,b2)如果两个向量的积小于0即a1*a2+b1*b2<o
//那么两个向量的夹角就小于0但是要注意共线的情况
//a1*b2=b1*a2 两向量共线
int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
	 cin>>x[i]>>y[i];
	int ans=0;
	for(int i=1;i<=n;i++)
	 for(int j=i+1;j<=n;j++)
	  for(int k=j+1;k<=n;k++)
	   if(juge(i,j,k)||juge(j,i,k)||juge(k,i,j))
	    ans++;
	cout<<ans<<endl;
	return 0;
} 

E.做计数

题意

给一个数n 然后求满足(i,j,k)这样的三元组的个数,满足 sqrt i+ sqrt j=sqrt k,并且满足i*j<n,只要 i j k 有一个数不同 就称是一个不同的三元组(ijk全是整数)

思路

看见根号 就平方得到
2sqrt(ij)=k-j-i,因为 ijk 都是整数 所以 2sqrt(jj)也是整数,所以 ij=m的平方 且 m方小于n 所以ij 是一个平方数,也就是说 i,j 都是平方说的因子,所以暴力枚举 求因子个数就可以了

代码

#include<iostream> 
#include<cmath>
using namespace std;
int main()
{
	int n;
	int ans=0;
	cin>>n;
	for(int i=1;i<=sqrt(n);i++)
	{
		int k=i*i;
		for(int j=1;j<=sqrt(k);j++)
		 {
		 	if(j==i)ans+=1;
		 	else
		 	  if(k%j==0)ans+=2;
		 }
	}
	cout<<ans<<endl;
	return 0;
}

F.拿物品

题意

给出n个物品,有两个属性ai,bi,两个轮流拿一次只能拿一个,ai的合为第一个人的收获,bi的和为第二个人的收获
两个人都希望自己的得分尽量比对方大(即最大化自己与对方得分的差)。
你需要求出两人都使用最优策略的情况下,最终分别会选择哪些物品,若有多种答案或输出顺序,输出任意一种。

思路

一个商品同时有ai bi ,这题其实不是看ai 和bi 的差 因为要是 都很小 都是1 1 拿了也没用,这题你拿走一个物品同时含有 ai 和bi 你拿走了你的ai 对手损失了 bi ,所以你赚的收获是 ai+bi 所以最优的策略是拿ai和bi和最大的,这样题目就迎刃而解了

代码

#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=200010;
struct node1
{
	int pos1,pos2;
} a[maxn];
struct node2
{
	int pos,key;
}b[maxn];
bool cmp(node2 x,node2 y)
{
	return x.pos>y.pos;//从大到小排序 
}
int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
	 cin>>a[i].pos1;
	for(int i=1;i<=n;i++)
	 cin>>a[i].pos2;
	for(int i=1;i<=n;i++)
	{
		b[i].pos=a[i].pos1+a[i].pos2;
		b[i].key=i;
	}
	sort(b+1,b+n+1,cmp);
	for(int i=1;i<=n;i++)
	 if(i&1)
	  cout<<b[i].key<<" ";
	cout<<endl;
	for(int i=1;i<=n;i++)
	 if(i%2==0)
	  cout<<b[i].key<<" ";
	cout<<endl;
	return 0;
	
}

G-判正误

题意

牛可乐有七个整数 a,b,c,d,e,f,g 并且他猜想a的d次方+b的e次方+d的f次方=g是否成立
。但 牛可乐无法进行如此庞大的计算。
请验证 牛可乐的猜想是否成立。

思路

快速幂,但是要注意模的值还有一次一次加放到一个数里,不要一次性的全加起判断,否则不知道为什么会哇

代码

#include<iostream>
const int MOD=1E9+7; 
using namespace std;
typedef long long ll;
ll quick_pow(ll a, ll b) {
    if(a == 0)
        return 0;
    if(b == 0)
        return 1;
    ll ans = 1;
    ll base = a % MOD;
    while(b) {
        if(b & 1)
            ans = (ans * base) % MOD;
        base = (base * base) % MOD;
        b >>= 1;
    }
    return ans;
}
int main()
{
	ll a,b,c,d,e,f,g,t;
	cin>>t;
	while(t--)
	{
		cin>>a>>b>>c>>d>>e>>f>>g;
		ll ans=0;
		ll x;
		x=quick_pow(a,d);
		ans+=x;
		x=quick_pow(b,e);
		ans+=x;
		x=quick_pow(c,f);
		ans+=x;
		if(ans==g)
		 cout<<"Yes"<<endl;
		else
		 cout<<"No"<<endl; 
	}
	return 0;
}
发布了8 篇原创文章 · 获赞 0 · 访问量 107

猜你喜欢

转载自blog.csdn.net/xgx984826498/article/details/104263104
今日推荐