2020牛客寒假算法基础集训营2

题目链接:2020牛客寒假算法基础集训营2
官方标程题解:标程

我先说一下我的感受 虽然我菜 但是还是想吐槽G题的概率取模,真恶心;

C:算概率

时隔几天过去才更新的c题,这个题是个dp;
看清楚题目输入的概率是取模后的概率,为了方便计算,我们都是假设分式 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;

.
搞懂这些,剩下就是DP了;

dp[ i ][ j ]集合表示当前i道题做对了j道题;
属性表示当前i道题做对了j道题的概率;(这里的所说的概率都是取模后的概率);

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
ll dp[2002][2002],p[2002];
 
int main()
{
    int n;
    cin >>n;
    for(int i=1;i<=n;i++) cin >>p[i];
    dp[0][0]=1;
    for(int i=1;i<=n;i++)
    {
        dp[i][0]=dp[i-1][0]*(mod+1-p[i])%mod;
        for(int j=1;j<=i;j++)
            dp[i][j]=dp[i-1][j]*(mod+1-p[i])%mod+dp[i-1][j-1]*p[i]%mod;
    }
    for(int i=0;i<=n;i++) cout <<dp[n][i]%mod<<" ";
}

.
.

D:数三角

我的做法是用向量做,暴力枚举任意的三个点,然后算出以每个点为顶点的角的两条边的向量乘积,看是否小于0,这里需要注意判断两个向量是否共线,也就是判断三个点是否共线:

#include <bits/stdc++.h>
using namespace std;
struct node
{
	int x,y;
}bb[505];
bool check(node a,node b,node c)//判断是否共线
{
	if((c.y-a.y)*(b.x-a.x)-(b.y-a.y)*(c.x-a.x)==0) return false;
	return true;
}
int get_mod(node a,node b,node c)
{
	return (a.x-b.x)*(a.x-c.x)+(a.y-b.y)*(a.y-c.y);
}
bool get_ans(node a,node b,node c)
{
	if(!check(a,b,c)) return false;
	if(get_mod(a,b,c)<0) return true;
	if(get_mod(b,a,c)<0) return true;
	if(get_mod(c,b,a)<0) return true;
	return false;
}
int main()
{
	int n;
	scanf("%d",&n);
	for(int i=0;i<n;i++) scanf("%d %d",&bb[i].x,&bb[i].y);
	int cnt=0;
	for(int i=0;i<n-2;i++)
	{
		for(int j=i+1;j<n-1;j++)
		{
			for(int k=j+1;k<n;k++)
			{
				if(get_ans(bb[i],bb[j],bb[k])) cnt++;
			}
		}
	}
	cout <<cnt<<endl;
}

E:做计数

贴个官方题解:
在这里插入图片描述
AC代码:

#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
map<pair<int,int> ,int> mp; 
int main()
{
    ll n;
    cin >>n;
    ll cnt=0;
    for(int i=1;i*i<=n;i++)
    {
    	int res=i*i;
    	for(int j=1;j*j<=res;j++)
    	{
    		if(res%j!=0) continue;
    		if(mp[make_pair(j,res/j)]!=1) cnt++;
    		mp[make_pair(j,res/j)]=1;
    		if(mp[make_pair(res/j,j)]!=1) cnt++;
    		mp[make_pair(res/j,j)]=1;
		}
	}
	cout <<cnt<<endl;
}

.

F.拿物品

这道题的贪心刚开始没想起来:
在这里插入图片描述
AC代码:

#include <bits/stdc++.h>
using namespace std;
int a[200005];

struct node
{
	int sum;
	int id;
}bb[200005];
bool cmp(node a,node b)
{
	return a.sum>=b.sum;
}
int main()
{
	int n;
	cin >>n;
	for(int i=0;i<n;i++) cin>>a[i]; 
	for(int i=0;i<n;i++)
	{
		int x;
		cin >>x;
		bb[i].sum=a[i]+x;
		bb[i].id=i+1;
	}
	sort(bb,bb+n,cmp);
	queue<int> q,p;
	for(int i=0;i<n;i++)
	{
		if(i%2==0) q.push(bb[i].id);
		else p.push(bb[i].id);
	}
	while(!q.empty()) cout <<q.front()<<" ",q.pop();
	cout <<endl;
	while(!p.empty()) cout <<p.front()<<" ",p.pop();
	cout <<endl;
}

.

G.判正误

当然这道题可以用pow来做,并且简单不会涉及到概率取模;

但是既然我用了快速幂,那么mod数它让随机取,本来用自己随机取的数字当作模数去过后台数据就是概率事件了,算了不吐槽了 ,,,,,靠运气吧;

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=1e9+7;
ll qk(ll a,ll b)
{
	ll res=1;
	while(b)
	{
		if(b&1) res=res*a%mod; 
		a=a*(ll)a%mod;
		b>>=1;
	}
	return res;
}
int main()
{
	int t;
	cin >>t;
	
	while(t--)
	{
		ll a,b,c,d,e,f,g;
		cin >>a>>b>>c>>d>>e>>f>>g;
		if(qk(a,d)+qk(b,e)+qk(c,f)==g) cout <<"Yes"<<endl;
		else cout <<"No"<<endl;
	}
	
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值