当前位置: 首页 > article >正文

牛客周赛 Round 60(A,B,C,D,E,F)

比赛链接

官方题解

这场基本都是数学题,官方题解讲的还不错,F能听懂的话其实不难。E是一个球盒模型的组合问题,F是化简递推式,成环时的解决方法很不错。


A 困难数学题

思路:

一个数异或两次结果为 0 0 0,异或四次结果也是 0 0 0

code:

#include <iostream>
#include <cstdio>
using namespace std;

int main(){
    cout<<0<<endl;
    return 0;
}

B 构造序列

思路:

如果正负数个数差不多,正常排就可以。

但是如果有一种数数量很多,比如正数很多,我们只能正负相间来排,不过我们可以让首尾为正数,这样用到的正数就会尽可能多,假设一共有 2 n + 1 2n+1 2n+1 个数,那么正数就会用到 n + 1 n+1 n+1 个。

所以看一下多的那种数是否超过 少的数+1 个,多出来的部分就用不到了。

code:

pypy3 的代码,不过应该挺好理解的

x,y = [int(i) for i in input().split()]

if x > y:
    t = x
    x = y
    y = t

if y > x+1:
    print(2*x+1)
else:
    print(x+y)

C 连点成线

思路:

其实可以发现问题可以转化成对每一行找两头的点算距离,以及对每一列找两头的点算距离,因为中间的点一定不可能是最长的,所以不用看。而且对于列的计算,我们可以将行列坐标翻转,然后按行来做。

那么我们现在只需要对每一行找两头的点算距离,之后翻转行列坐标再算一次即可。这一步做法很多,先排序,可以枚举行坐标然后双指针找两端的点,也可以按横坐标升序来枚举点的横坐标,二分来找两端的纵坐标。

code:

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
#define pii pair<int,int>
const int maxn=1e5+5;

int n,m;
pii a[maxn];

int calc(){//x相同 y的最大差值 
	sort(a+1,a+m+1);
	int ans=0;
	for(int l=1,r;l<=m;l=r+1){
		r=upper_bound(a+1,a+m+1,pii(a[l].first,n))-a-1;
		ans=max(ans,a[r].second-a[l].second);
	}
	return ans;
}

int main(){
	cin>>n>>m;
	for(int i=1;i<=m;i++){
		auto &[x,y]=a[i];
		cin>>x>>y;
	}
	int ans=calc();
	for(int i=1;i<=m;i++){
		auto &[x,y]=a[i];
		swap(x,y);
	}
	ans=max(ans,calc());
	cout<<ans<<endl;
	return 0;
} 

D 我们N个真是太厉害了

思路:

说白了就是给你 n n n 个数,问你用这些数无法表示的最小的数是多少。

我们可以对 n n n 个数排个序,假设用前 i − 1 i-1 i1 个数最大可以表示到 m x mx mx(也就是说前 i − 1 i-1 i1 个数可以表示 0 ∼ m x 0\sim mx 0mx 任何一个数),如果 a i ≤ m x + 1 a_i\le mx+1 aimx+1,那么低于 m x mx mx 的数可以用前 i − 1 i-1 i1 个数来凑,而高于 m x mx mx 的数可以通过使用 a i a_i ai 来凑,最多可以凑到 a i + m x a_i+mx ai+mx

否则如果 a i > m x + 1 a_i> mx+1 ai>mx+1,那么就会出现至少 m x + 1 mx+1 mx+1 无法被表示的情况,因为我们已经排好序了,后续的 a j a_j aj 肯定都 > m x + 1 >mx+1 >mx+1,所以最小的无法表示的数就是 m x + 1 mx+1 mx+1

我们维护 m x mx mx,如果能继续往下凑就加入 m x mx mx,否则我们就找到了第一个无法表示的数,也就是答案。

code:

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=1e5+5;

int T,n;
int a[maxn];

int calc(){
	int mx=0;
	for(int i=1;i<=n;i++){
		if(a[i]>mx+1)return mx+1;
		else {
			mx+=a[i];
			if(mx>=n)return -1;
		}
	}
	return -1;
}

int main(){
	cin>>T;
	while(T--){
		cin>>n;
		for(int i=1;i<=n;i++)cin>>a[i];
		sort(a+1,a+n+1);
		int ans=calc();
		if(~ans)cout<<ans<<endl;
		else cout<<"Cool!"<<endl;
	}
	return 0;
}

E 折返跑

思路:

因为两边的杆子要占两个格子,所以实际上能移动的距离是 n − 2 n-2 n2。因为跑 m m m 趟,第一趟和最后一趟不移动杆子,所以实际上就只移动了 m − 1 m-1 m1 次杆子。

我们每次至少移动一格杆子,不能把杆子移动的总长度超过两个杆子的总距离。而且我们还能把移动左右两边的杆子都看作是移动一根杆子,因为不管移动哪个杆子,两个杆子的相对距离变化是一样的。

这就有点像球盒模型了。我们把一格看成一个小球,把每一趟移动杆子的距离看成盒子,把球放入盒子看成让这一趟移动杆子的距离增加一格。那么这就是一个将 n − 2 n-2 n2 个相同的小球放入 m − 1 m-1 m1 个不同盒子,不能空盒,可以剩球的球盒模型。

球盒模型不可以剩球,但是我们可以多加入一个新的盒子,将 n − 2 n-2 n2 个相同的小球放入 m m m 个不同盒子,放入新盒的球看作剩下的球就行了(也就是垃圾桶)。这样的话就转化成了经典的球盒模型,使用隔板法来做。

n − 2 n-2 n2 个相同的小球放入 m m m 个不同盒子,不能空盒。既然不能空盒,就向每个盒子里预先加入一个小球, m − 1 m-1 m1 个不能空盒的盒子各放入一个,球剩下 n − m − 1 n-m-1 nm1 个,这样就转化成了 n − m − 1 n-m-1 nm1 个相同的小球放入 m m m 个不同盒子,可以空盒 的问题了,向 n − m − 1 + ( m − 1 ) = n − 2 n-m-1+(m-1)=n-2 nm1+(m1)=n2 个位置上放入 m − 1 m-1 m1 个隔板,其余位置放小球,这样分割出来的 m m m 个区间看作放入盒子的方法,方案数就是 C n − 2 m − 1 C_{n-2}^{m-1} Cn2m1 了。

code:

#include <iostream>
#include <cstdio>
using namespace std;
const int maxn=1e6+5;
const int N=1e6;
typedef long long ll;
const ll mod=1e9+7;

ll qpow(ll a,ll b){
	ll base=a%mod,ans=1;
	b%=mod;
	while(b){
		if(b&1)ans=ans*base%mod;
		base=base*base%mod;
		b>>=1;
	}
	return ans;
}
ll inv(ll x){return qpow(x,mod-2);}

int T,n,m;
ll fac[maxn],ifac[maxn];

ll C(ll x,ll y){//C_x^y
	return fac[x]*ifac[y]%mod*ifac[x-y]%mod;
}

int main(){
	cin>>T;
	fac[0]=1;
	for(int i=1;i<=N;i++)fac[i]=fac[i-1]*i%mod;
	ifac[N]=inv(fac[N]);
	for(int i=N;i>=1;i--)ifac[i-1]=ifac[i]*i%mod;
	while(T--){
		cin>>n>>m;
		cout<<C(n-2,m-1)<<endl;
	}
	return 0;
}

F 口吃

思路:

这个题在官方题解里讲的其实挺好的。

假设 f i f_i fi 表示讲第 i i i 个字的期望讲字的个数,根据题意可知 f n = 1 f_n=1 fn=1。根据题意不难列出: f 1 = 1 + a 1 a 1 + b 1 f 2 + b 1 a 1 + b 1 f 1 f_1=1+\dfrac{a_1}{a_1+b_1}f_2+\dfrac{b_1}{a_1+b_1}f_1 f1=1+a1+b1a1f2+a1+b1b1f1 f i = 1 + a i 2 ( a i + b i ) 2 f i + 1 + 2 a i b i ( a i + b i ) 2 f i + b i 2 ( a i + b i ) 2 f i − 1 f_i=1+\dfrac{a_i^2}{(a_i+b_i)^2}f_{i+1}+\dfrac{2a_ib_i}{(a_i+b_i)^2}f_{i}+\dfrac{b_i^2}{(a_i+b_i)^2}f_{i-1} fi=1+(ai+bi)2ai2fi+1+(ai+bi)22aibifi+(ai+bi)2bi2fi1
整理可得: f 1 = f 2 + a 1 + b 1 a 1 f_1=f_2+\dfrac{a_1+b_1}{a_1} f1=f2+a1a1+b1 ( a i 2 + b i 2 ) f i = a i 2 f i + 1 + b i 2 f i − 1 + ( a i + b i ) 2 (a_i^2+b_i^2)f_i=a_i^2f_{i+1}+b_i^2f_{i-1}+(a_i+b_i)^2 (ai2+bi2)fi=ai2fi+1+bi2fi1+(ai+bi)2
发现问题比较麻烦,因为这个递推式没法递推,如果我们从小到大递推的话,我们算 f i f_i fi 需要预先知道 f i + 1 f_{i+1} fi+1 的值,但是我们又没算出来,而算 f i + 1 f_{i+1} fi+1 的值又需要知道 f i f_i fi 的值,这时候就成环了(或者叫死锁)。

如果我们能把 f i + 1 f_{i+1} fi+1 f i − 1 f_{i-1} fi1 的其中一个转化为 f i f_i fi,就可以打破这个死锁局面了。发现第一个 f 1 = f 2 + a 1 + b 1 a 1 f_1=f_2+\dfrac{a_1+b_1}{a_1} f1=f2+a1a1+b1 的式子可以带入到当 i = 2 i=2 i=2 时的 ( a 2 2 + b 2 2 ) f 2 = a 2 2 f 3 + b 2 2 f 1 + ( a 2 + b 2 ) 2 (a_2^2+b_2^2)f_2=a_2^2f_{3}+b_2^2f_{1}+(a_2+b_2)^2 (a22+b22)f2=a22f3+b22f1+(a2+b2)2 中,这样可以把 f 1 f_1 f1 转化为 f 2 f_2 f2,这时整个式子就变为了 f 2 f_2 f2 f 3 f_3 f3 的关系式,化简后会得到一个形为 f 2 = P ∗ f 3 + Q f_2=P*f_3+Q f2=Pf3+Q 的形式

而这个 f 2 f_2 f2 f 3 f_3 f3 的关系式可以类似地再次带入到 i = 3 i=3 i=3 时的式子 2 2 2 里,同理可以得到 f 3 f_3 f3 f 4 f_4 f4 的关系式,是一个形如 f 3 = P ∗ f 4 + Q f_3=P*f_4+Q f3=Pf4+Q 的关系式,同理继续带入。

发现我们可以去递推算每一对 P , Q P,Q P,Q,然后从 n n n 1 1 1 递推 f 1 f_1 f1 即可。

假设 f i − 1 = P i − 1 ∗ f i + Q i − 1 f_{i-1}=P_{i-1}*f_{i}+Q_{i-1} fi1=Pi1fi+Qi1,带入式子 2 2 2 得: ( a i 2 + b i 2 ) f i = a i 2 f i + 1 + b i 2 f i − 1 + ( a i + b i ) 2 (a_i^2+b_i^2)f_i=a_i^2f_{i+1}+b_i^2f_{i-1}+(a_i+b_i)^2 (ai2+bi2)fi=ai2fi+1+bi2fi1+(ai+bi)2 ( a i 2 + b i 2 ) f i = a i 2 f i + 1 + b i 2 ( P i − 1 ∗ f i + Q i − 1 ) + ( a i + b i ) 2 (a_i^2+b_i^2)f_i=a_i^2f_{i+1}+b_i^2(P_{i-1}*f_{i}+Q_{i-1})+(a_i+b_i)^2 (ai2+bi2)fi=ai2fi+1+bi2(Pi1fi+Qi1)+(ai+bi)2 ( a i 2 + b i 2 ) f i = a i 2 f i + 1 + b i 2 P i − 1 ∗ f i + b i 2 Q i − 1 + ( a i + b i ) 2 (a_i^2+b_i^2)f_i=a_i^2f_{i+1}+b_i^2P_{i-1}*f_{i}+b_i^2Q_{i-1}+(a_i+b_i)^2 (ai2+bi2)fi=ai2fi+1+bi2Pi1fi+bi2Qi1+(ai+bi)2 ( a i 2 + b i 2 − b i 2 P i − 1 ) f i = a i 2 f i + 1 + b i 2 Q i − 1 + ( a i + b i ) 2 (a_i^2+b_i^2-b_i^2P_{i-1})f_i=a_i^2f_{i+1}+b_i^2Q_{i-1}+(a_i+b_i)^2 (ai2+bi2bi2Pi1)fi=ai2fi+1+bi2Qi1+(ai+bi)2 f i = a i 2 a i 2 + b i 2 − b i 2 P i − 1 f i + 1 + b i 2 Q i − 1 + ( a i + b i ) 2 a i 2 + b i 2 − b i 2 P i − 1 f_i=\dfrac{a_i^2}{a_i^2+b_i^2-b_i^2P_{i-1}}f_{i+1}+\dfrac{b_i^2Q_{i-1}+(a_i+b_i)^2}{a_i^2+b_i^2-b_i^2P_{i-1}} fi=ai2+bi2bi2Pi1ai2fi+1+ai2+bi2bi2Pi1bi2Qi1+(ai+bi)2因此: P i = a i 2 a i 2 + b i 2 − b i 2 P i − 1 , Q i = b i 2 Q i − 1 + ( a i + b i ) 2 a i 2 + b i 2 − b i 2 P i − 1 P_i=\dfrac{a_i^2}{a_i^2+b_i^2-b_i^2P_{i-1}},Q_i=\dfrac{b_i^2Q_{i-1}+(a_i+b_i)^2}{a_i^2+b_i^2-b_i^2P_{i-1}} Pi=ai2+bi2bi2Pi1ai2,Qi=ai2+bi2bi2Pi1bi2Qi1+(ai+bi)2

code:

#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
const ll mod=1e9+7;

ll qpow(ll a,ll b){
	ll base=(a%mod+mod)%mod,ans=1;
	b%=mod;
	while(b){
		if(b&1)ans=ans*base%mod;
		base=base*base%mod;
		b>>=1;
	}
	return ans;
}
ll inv(ll x){return qpow(x,mod-2);}

int n;
ll a[maxn],b[maxn];
ll p[maxn],q[maxn];
ll f[maxn];

int main(){
	cin>>n;
	for(int i=1;i<n;i++)cin>>a[i];
	for(int i=1;i<n;i++)cin>>b[i];
	
	p[1]=1;
	q[1]=(a[1]+b[1])%mod*inv(a[1])%mod;
	for(int i=2;i<n;i++){
		ll A=a[i]*a[i]%mod,B=b[i]*b[i]%mod,C=(a[i]+b[i])*(a[i]+b[i])%mod;
		ll t=inv(((A+B-B*p[i-1])%mod+mod)%mod);
		p[i]=A*t%mod;
		q[i]=(B*q[i-1]+C)%mod*t%mod;
	}
	f[n]=1;
	for(int i=n-1;i>=1;i--){
		f[i]=p[i]*f[i+1]+q[i];
		f[i]%=mod;
	}
	cout<<f[1];
	return 0;
}

http://www.kler.cn/a/308472.html

相关文章:

  • JWT深度解析:Java Web中的安全传输与身份验证
  • Golang | Leetcode Golang题解之第559题N叉树的最大深度
  • C获取程序名称的方法
  • 【go从零单排】Timer、Epoch 时间函数
  • 3.5【数据库系统】ER图
  • 中文书籍对《人月神话》的引用(161-210本):微软的秘密
  • 构建“零工市场小程序”,服务灵活就业“大民生”
  • Baumer工业相机堡盟工业相机如何通过BGAPI SDK设置相机的图像剪切(ROI)功能(C语言)
  • com.microsoft.sqlserver:sqljdbc4:jar:4.0 was not found产生原因及解决步骤
  • 电商店群模式如何利用云分账实现自动化资金管理
  • 闲云野记:24915
  • 技术上,如何复现 o1?
  • 易于理解和实现的Python代码示例
  • 数据中心服务器与存储运维的深度实践与挑战
  • 部署自己的对话大模型,使用Ollama + Qwen2 +FastGPT 实现
  • ThinkCMF框架任意内容包含漏洞的讲解
  • 简化登录流程,助力应用建立用户体系
  • 《程序猿之设计模式实战 · 池化思想》
  • MySql批量迁移数据库
  • macOS使用brew安装并配置python环境
  • visual studio2015安装番茄助手
  • Spring Boot-日志相关问题
  • android13隐藏桌面底部白线
  • STM32巡回研讨会总结(2024)
  • Kafka日志索引详解与常见问题分析
  • 【LLM】为什么要PPO