“蔚来杯“2022牛客暑期多校训练营1 GADI

这篇博客涵盖了三场编程竞赛的解题策略。第一场涉及处理字符串,检查是否全由9组成;第二场是覆盖区间问题,求解覆盖所需的最小长度;第三场涉及概率计算,用到了概率dp和除数取模的知识。博主分享了每道题目的解题思路和代码实现,并提供了快速幂等算法来简化除数取模操作。
摘要由CSDN通过智能技术生成

G.Villages: Landlines

官方题解:
请添加图片描述
请添加图片描述
代码如下:

#include<bits/stdc++.h>
using namespace std;
string s;
typedef long long ll;
bool flag=0;
int main()
{
	cin>>s;
	if(s.length()==1)
	{
	    cout<<s;
	    return 0;
	}
	ll len=s.length()-1;
	for(ll i=0;i<len;i++)
	{
		if(s[i]!='9')
		{
		    flag=1;
		    break;
		}	
	}
	if(flag)
	{
		for(ll i=1;i<=len;i++)
		  cout<<9;
	}
	else
	{
		cout<<s;
		return 0;
	}
	return 0;
	
}

A.Villages: Landlines

请添加图片描述
解:覆盖区间问题
代码如下:

#include<bits/stdc++.h>
using namespace std;
int n;
const int N=2e5+11;
typedef long long ll;
struct node
{
	ll l,r;
}e[N];
bool cmp(node x,node y)
{	
	return x.l<y.l;
}
ll ans=0;
int main()
{
	cin>>n;
ll x,y;
	for(int i=1;i<=n;i++)
	{
		cin>>x>>y;
	    e[i].l=x-y;
	    e[i].r=y+x;
	}
	sort(e+1,e+1+n,cmp);
	ll r=e[1].r;
	for(int i=2;i<=n;i++)
	{
		if(e[i].l>r)
		    ans+=e[i].l-r;
		r=max(e[i].r,r);
	}
	cout<<ans;
	return 0;
}

D.Mocha and Railgun

请添加图片描述
在这里插入图片描述
代码如下:

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
double x,y,r,d,t;
double ans,m,th,l;
void solve()
{
	double dis=sqrt(x*x+y*y);
	double y1=sqrt(r*r-(dis-d)*(dis-d)),y2=sqrt(r*r-(dis+d)*(dis+d));
	d=sqrt((y1-y2)*(y1-y2)+(2*d)*(2*d));
    double th=d/(2*r);
	ans=2*r*asin(th);
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cin>>t;
	while(t--)
	{
		cin>>r>>x>>y>>d;
	    solve();
		printf("%.10lf",ans);
	}
	return 0;
 } 

I.Chiitoitsu

官方题解:
在这里插入图片描述
请添加图片描述
解:

1.知识点概率dp除数取模
其中"除数取模":
根据 费马小定理 1/a % m == am-2%m , 其中m要为素数。
所以:(b/a)%m == (b*am-2)%m。(快速幂)
函数代码如下:

int work(int a, int m)//1/a取模
{
    int ans = 1;
    int t=m-2;
    while(t)
    {
        if(t & 1)
          ans=ans* a % m;
        a=a*a%mod;
        t>>=1;
    }
    return ans;
}

2.转移方程:

dp[i][j]=(f[i+1][j-1]*t1*t2   +   f[i][j-1]*t2*t3   +   1 )%mod;

其中

  • t1 =(13-i*2)*3
  • t2=j-t1
  • t3=work(j,mod)
    代码如下:
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long ll;
ll dp[30][211];
const int mod=1e9+7;
int T;
ll s,r;
string S;
map<string,int>e;
ll work(ll a, ll m)
{
    ll ans = 1;
   ll t=m-2;
    while(t)
    {
        if(t & 1)
          ans=ans*a%mod;
        a=a*a%mod;
        t>>=1;
    }
    return ans;
}

void solve()
{
	cin>>S;
	e.clear();
	s=0;
	for(int i=0;i<S.length();i+=2)
	{
		if(e[S.substr(i,2)])
		  s++;
		else
		  e[S.substr(i,2)]=1;
	}
}
void init()
{
	for(int i=6;i>=0;i--)
	{
		ll t1=(13-i*2)*3;
		for(int j=t1;j<=123;j++)
		{
			ll t3=j-t1;
			ll t2=work(j,mod); 
			dp[i][j]=(dp[i+1][j-1]%mod*t1%mod*t2%mod +dp[i][j-1]%mod*t2%mod*t3%mod + 1 )%mod; // 后面数据很大,每次相乘都要取模一次
		}
	}
}
int main()
{
	init();
	cin>>T;
	for(int i=1;i<=T;i++)
	{
		solve();
		cout<<"Case #"<<i<<": "<<dp[s][123]<<endl;
	}
	
}

mood:学习学习还是学习
请添加图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dai _ tu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值