牛客小白月赛71 补题记录

AB:
C:
可以转化为比较对数,然后直接模拟即可(long double 128位 表示范围\(-1.2 \times 10^{-4932}~1.2 \times 10^{4932}\)
代码如下:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
//------------------------
int main(void)
{
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	ll p, q;
	cin>>p>>q;
	long double M=logl(1e18);
	int n=2;
	while(++n){
		long double t=logl(p)*q;
		if(t-M>0) break;
		long long tem=pow(p, q);
		p=q;
		q=tem;
	}
	cout<<n-1<<endl;
	return 0;
}

D:
tricks: 一共有两个属性,每个物品都有这两个属性,有两组物品,可以建立一个二维坐标系,来观察一下

  • 猫猫的友善值作为横坐标,期望友善值作为纵坐标
  • 主人的期望友善值作为横坐标,友善值作为纵坐标
  • 将猫猫按照友善值从小到大排序,主人按照期望友善值从小到大排序。要求的答案就是对于每个猫猫,它的左上部分的主人的友善值的最大值。具体来说就是:遍历每一个猫猫,用指针遍历的方式遍历主人,取主人友善值的最大值,然后离线更新猫猫的答案
    代码如下:
#include <bits/stdc++.h>
using namespace std;
struct node{
	int x, y, id;
};
bool cmp(node a, node b){
	return a.x<b.x;
}
int main(void)
{
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	int n, m;
	cin>>n>>m;
	vector<node> a(n), b(m);
	for(int i=0; i<n; i++) cin>>a[i].x;
	for(int i=0; i<n; i++) cin>>a[i].y;
	for(int i=0; i<n; i++) a[i].id=i;
	for(int i=0; i<m; i++) cin>>b[i].y;
	for(int i=0; i<m; i++) cin>>b[i].x;
	sort(a.begin(), a.end(), cmp);
	sort(b.begin(), b.end(), cmp);
	vector<int> ans(n);
	int mx=-1, last=0;
	for(int i=0; i<n; i++){
		while(last<m && b[last].x<=a[i].x){
			mx=max(mx, b[last].y);
			last++;
		}
		if(mx>=a[i].y) ans[a[i].id]=mx;
		else ans[a[i].id]=-1;
	}
	for(int i=0; i<n; i++){
		cout<<ans[i]<<" ";
	}
	cout<<endl;
	return 0;
}

E:

  • a=b
    • a=b=1,print 1
    • a=b \(\neq\) 1 print 0
  • a \(\neq\) b
    • WLOG b>a,根据更相减损之术,有:
    • \[gcd(a+c, b+c) = gcd(a+c, b-a) = d \neq 1 \]

    • 因此,枚举每一个b-a的因子d(可在\(O(\sqrt n)\)内完成),\(O(1)\) 算出使得\(d \mid a+c\)的最小c(具体来说就是, \((d-a\%d)\%d\)

代码如下:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll calc(ll a, ll d)
{
	return (d-a%d)%d;
}
int main(void)
{
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	ll a, b;
	cin>>a>>b;
	if(a==b){
		if(a==1) cout<<1<<endl;
		else cout<<0<<endl;
		return 0;
	}
	if(a>b) swap(a, b);
	ll tem=b-a;
	ll ans=-1;
	for(ll i=1; i<=(ll)sqrt(tem); i++){
		if(tem%i==0){
			if(i!=1){
				ll t=calc(a, i);
				if(ans==-1) ans=t;
				else ans=min(ans, t);
			}
			if(tem/i != 1){
				ll t=calc(a, tem/i);
				if(ans==-1) ans=t;
				else ans=min(ans, t);
			}
		}
	}
	cout<<ans<<endl;
	return 0;
} 

F:
对于第i次询问,有\(2^{i}\)种可能:(下面以i=3为例)

  • 选择1个 \(1 \times (a_{1}+a_{2}+a_{3})\)
  • 选择2个 \(2 \times (a_{1}+a_{2}) + 2 \times (a_{1}+a_{3}) + 2 \times (a_{2}+a_{3})\)
  • 选择3个 \(3 \times (a_{1}+a_{2}+a_{3})\)
  • 可以看出,\(a_{1}, a_{2}, a_{3}\) 地位同等重要,最后答案是\(\frac{上面求和}{2^{3}} = \frac{x}{2^{3}} \times \sum_{i=1}^{3} a_{i}\),所以只要求对于每个i的x即可
    对于第i次询问,求\(x_{i}\):

\[\begin{aligned} x_{i} &= 1 \times C_{i-1}^{0} + 2 \times C_{i-1}^{1} + \dots + i \times C_{i-1}^{i-1} \\ &= 2^{i-1} + 1 \times C_{i-1}^{1} + \dots + (i-1) \times C_{i-1}^{i-1} \\ &=2^{i-1} + (i-1) \times 2^{i-1-1} \\ &=\frac{i+1}{4} \times \sum_{i=1}^{i} a_{i} \end{aligned} \]

代码如下:

#include <bits/stdc++.h>
using namespace std;
const int MAXN=2e5+10;
const int mod=998244353;
typedef long long ll;
//--------------------------
int inv[MAXN];
ll quick(ll a, ll b)
{
	ll ret=1;
	while(b){
		if(b&1) ret=ret*a%mod;
		a=a*a%mod;
		b>>=1;
	}
	return ret;
}
int main(void)
{
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	int n;
	cin>>n;
	vector<ll> a(n+1);
	for(int i=1; i<=n; i++) cin>>a[i];
	for(int i=1; i<=n; i++) a[i]+=a[i-1], a[i]%=mod; //注意,这里前缀和要取模,要不然a[i]最大是9*10^13,后面*a[i]的时候,可能会爆范围 
	ll inv=quick(4, mod-2);
	for(int i=1; i<=n; i++) cout<<(i+1)*inv%mod*a[i]%mod<<" \n"[i==n];
	return 0;
}
posted @ 2023-04-22 08:53  YianSanren  阅读(35)  评论(0)    收藏  举报