牛客寒假训练营3

本场赛时5题,被B和H卡了一下,后面的中档题没时间开。觉得是见的比较少,前面的题难度不高但由于思考和用了比较复杂的方法浪费了不少时间。

本场链接:寒假训练营3

B. Random

考察点: 质数,gcd

之前没遇到过随机生成的题,一直在想特例怎么办。

赛时我用了筛法,由于本题不是让用这个,所以数据规模上不太匹配,我一直没写.

思路

由于数据是随机的,所以非常难遇到一直找不到两个都是不同质数的数,直接 n 2 n^2 n2暴力就行

这里贴上筛法的代码,让本题变得有意义一些

cpp 复制代码
void pre()
{
	v[1]=1;
	for(int i=1; i<N; i++)
	{
		if(!v[i]) f.pb(i);
		for(int j=0; j<min(N,(int)f.size())&&i*f[j]<=N; j++)
		{
			v[i*f[j]]=1;
			if(i%f[j]==0) break;
		}
	}
}
void check(vector<int>&a)
{
	unordered_map<int,int> mp;
	k=0;
	for(int i=0; i<n; i++)
	{
		int x=a[i];
		for(int j=0; j<f.size(); j++)
		{
			if(x%f[j]==0)
			{
				if(mp[f[j]])
				{
					k=1;
					cout << mp[f[j]] << ' ' << a[i] << endl;
					return;
				}
				else
				{
					mp[f[j]]=a[i];
					while(x%f[j]==0&&f[j]) x/=f[j];
				}
			}
			if(x==1) break;
		}
	}
}
void solve()
{
	cin >> n; 
	vector<int> a(n);
	map<int,int> p;
	for(int &i:a) cin >> i,p[i]++;
	for(auto [x,y]:p)
	{
		if(x!=1&&y>1)
		{
			cout << x << ' ' << x << endl;
			return;
		}
	}
	check(a);
	if(!k) cout << -1 << endl;
}

J. Branch of Faith

考察点: 二叉树,计算

思路

法1:二进制的每一位刚好就是二叉树每一层的数量,可利用此特性进行模拟。

​ 遇到的问题:log2计算太大的数字如(1e18)的时候会导致精度丢失,还是一点点左移保险

法2:将二叉树前x层之和存到vector里,每次用lower_bound定位到当层并计算

代码1

cpp 复制代码
// Problem: Branch of Faith
// Contest: NowCoder
// URL: https://ac.nowcoder.com/acm/contest/120563/J
// Memory Limit: 512 MB
// Time Limit: 2000 ms

int cal(int x)
{
	int len=0;
	while(x) x>>=1LL,len++;
	int p=(1LL<<len)-1;
	int q=(1LL<<len-1)-1;
	int res=min(p,n)-q;
	return res;
}
void solve()
{
	int q;
	cin >> n >> q;
	while(q--)
	{
		int x;
		cin >> x;
		int ans=cal(x);
		cout << ans << endl;
	}
}

代码2:

cpp 复制代码
void pre()
{
	for(int i=1; i<=INF; i*=2) f.pb(i-1);
}
void solve()
{
	cin >> n;
	int q;
	cin >> q;
	while(q--)
	{
		int x;
		cin >> x;
		int cu=lower_bound(all(f),x)-f.begin();//当层
		int num=1LL<<cu-1;//当层总数量
		int k=n-f[cu-1];
		cout << min(num,k) << endl;
	} 
}

F. Energy Synergy Matrix

考察点: 博弈,思维

思维

  • 需要注意的是,小红和小小红不是同一个人
  • 小红的任务是在小小红所在的另一行在不让小紫放到此行的情况下尽量靠右
  • 小紫的任务是在小小红所在的这一行尽量靠左的放
  • 大概是这么个情况,其中⚪代表小红,菱形表示小紫
  • 先说结论: a n s = ( n − 1 ) + n / 5 ans=(n-1)+n/5 ans=(n−1)+n/5
    • 首先n-1是除了第一列以外向右走的步数
    • n/5是上下变换的步数。通过观察不难发现,小小红总是在菱形所在的前一列进行变换,但是由于题目中说到达当列的任意位置都行,所以这个推迟了一步,每次就到了菱形这一列。而菱形列刚好是5的倍数。

H. Tic Tac DREAMIN'

考察点: 数学,计算几何

思路1

  • 用二分不断枚举x的位置,check中用叉积计算面积来判断。
    • 需要注意的是,叉积具有方向性,如果 A C → \overrightarrow{AC} AC 在 A B → \overrightarrow{AB} AB 的左侧,则 A B → × A C → > 0 \overrightarrow{AB}×\overrightarrow{AC}>0 AB ×AC >0。所以计算面积需要取绝对值
    • 面积公式为 1 2 ⋅ ∣ A B → × A C → ∣ \frac{1}{2}·|\overrightarrow{AB}×\overrightarrow{AC}| 21⋅∣AB ×AC ∣

思路2

  • 由于用叉积计算面积的时候x是唯一的未知数,所以可以直接解出来
    • 需要注意的是,正着计算叉积的时候直接取绝对值即可,但是倒着推式子就要提前加上符号再推导

代码1:

cpp 复制代码
double xa,ya,xb,yb; 
double g(double x){
    return -(yb-ya)*x + (yb-ya)*xa - (xb-xa)*ya;
}

void solve(){
    cin>>xa>>ya>>xb>>yb;
    if(yb==ya){
        double t=fabs((xb-xa)*ya);
        if(fabs(t-4.0)<=1e-9) cout<<0.0<<"\n";
        else cout<<"no answer\n";
        return;
    }
    double A=-(yb-ya);
    double B=(yb-ya)*xa-(xb-xa)*ya;
    double x0=-B/A;
    double l=x0,r=1e18;
    for(int i=0;i<200;i++){
        double mid=(l+r)/2;
        if(fabs(g(mid))<4.0) l=mid;
        else r=mid;
    }
    cout<<fixed<<setprecision(10)<<((l+r)/2)<<"\n";
}

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    solve();
    return 0;
}

代码2:

cpp 复制代码
void solve()
{
	cin >> xa >> ya >> xb >> yb;
	if(ya==yb)
	{
		double p=fabs(ya)*fabs(xa-xb)/2;
		if(p==2) cout << 0.00000 << endl;
		else cout << "no answer" << endl;
		return ;
	}
	a=xb*ya-xa*yb;
	b=yb-ya;
	double x=(-4-a)/b;
	cout << fixed << setprecision(15) << x << endl;
}	

C. Inverted World

考察点: 思维

思路

  • 首先可以明确,最终的结果是01010101···或者是10101010···
  • 我们分别假设最终变成这些串,通过计算后取操作数比较小的那个
  • 设原始串是100011001001,以第二种串10101010···为例:
标号 1 2 3 4 5 6 7 8 9 10 11 12
目标串 1 0 1 0 1 0 1 0 1 0 1 0
原串 1 0 0 0 1 1 0 0 1 0 0 1

子串不必连续,找的第一个操作字串就是本来就刚好吻合的,剩下的:

标号 3 6 7 11 12
目标串 1 0 1 1 0
原串 0 1 0 0 1

剩下的就一点点"缝合",如果有可以接上的就接上,接不上就另起一列。在这个例子中,我们可以选择3,6,11,12为一个操作字串0101,7是另一个

cpp 复制代码
int cal(string p)
{
	vector<int> v;
	for(int i=0; i<s.size(); i++)
		if(s[i]!=p[i]) v.pb(s[i]-'0');
	if(v.size()==0) return 0;
	int val=1,num=v[0];
	int cnt0=0,cnt1=0;//此时需要的数
	if(v[0]==1) cnt0++;
	else cnt1++;
	for(int i=1; i<v.size(); i++)
	{
		if(v[i])
		{
			cnt0++;
			if(cnt1) cnt1--;
			else val++;
		}
		else
		{
			cnt1++;
			if(cnt0) cnt0--;
			else val++;
		}
	}
	return val;
}
void solve()
{
	cin >> n >> s;
	string s1,s2;
	char x='0';
	for(int i=0; i<n; i++)
	{
		s1+=x;// 01
		x^=1;
		s2+=x;// 10
	}
	int k1=cal(s1);
	int k2=cal(s2);
	cout << min(k1,k2) << endl;
}

A. 宙天

考察点: 简单语法

思路

  • 利用 s q r t sqrt sqrt下取整的性质, k = s q r t ( x ) k=sqrt(x) k=sqrt(x),直接判断 k ( k + 1 ) k(k+1) k(k+1)与 x x x是否相等即可

G. スピカの天秤

考察点: 简单模拟

思路

  • 分类讨论,对每种情况进行模拟,等到了下一种状态就输出

本次补题主要有这几点:

  1. B题随机二字背后的深意
  2. J题学会多利用二进制的性质
  3. F题比较有意思的思维博弈和找规律
  4. H题对叉积的进一步理解
  5. C题对题目的不断拆解和转化
相关推荐
24白菜头1 小时前
2026-2-23:LeetCode每日一题(动态规划专项)
笔记·学习·算法·leetcode·动态规划
小龙报2 小时前
【算法通关指南:数据结构与算法篇】二叉树相关算法题:1.美国血统 American Heritage 2.二叉树问题
c语言·数据结构·c++·算法·深度优先·广度优先·宽度优先
啊阿狸不会拉杆2 小时前
《计算机视觉:模型、学习和推理》第 9 章-分类模型
人工智能·python·学习·算法·机器学习·计算机视觉·分类
yyjtx2 小时前
DHU上机打卡D29
数据结构·c++·算法
多恩Stone2 小时前
【3D-AICG 系列-13】Trellis 2 的 SC-VAE 的 Training Loss 细节
人工智能·算法·3d·aigc
feng_you_ying_li2 小时前
类和对象(中)
c++
Aaron15882 小时前
RFSOC与ADRV9009、AD9026、AD9361技术指标及应用场景对比分析
人工智能·算法·fpga开发·硬件工程·信息与通信·信号处理·基带工程
●VON2 小时前
HarmonyOS应用开发实战(基础篇)Day10 -《鸿蒙网络请求实战》
网络·学习·华为·harmonyos·鸿蒙·von
学编程的闹钟2 小时前
E语言软件开发全流程解析
学习