牛客 周赛101 20250726

牛客 周赛101 20250726

https://ac.nowcoder.com/acm/contest/113313

A:

题目大意:

void solve(){
	int a;
	cin>>a;
	cout<<fixed<<setprecision(6)<<(double)150*log(a);
}

签到

B:
题目大意:

image-20250725184858911

void solve(){
	int n;
	cin>>n;
	int a=0,b=0,c=0,d=0;
	for (int i=1;i<=n;i++){
		if (i>=5&&i%5==0) a+=2;
		if (i>=5&&(i-5)%10==0) b+=1;
		if (i>=20&&i%20==0) c+=3;
		else (d+=2); 
	}
	cout<<a<<' '<<b<<' '<<c<<' '<<d;
}

模拟题

C:

题目大意:给定 \(n\) ,从 \([1,n]\) 的排列中选取任意个数进行异或操作,输出最大的异或值

void solve(){
	LL n;
	cin>>n;
	int d=log2(n)+1;
	cout<<(LL)pow(2,d)-1<<endl;
}

显然 \([1,n]\) 能构成的最大异或数是 \([1,n]\) 上能组成的每个二进制位上全 \(1\) 的数

D:
题目大意:

image-20250725185137822

void solve(){
	int n,m;
	cin>>n>>m;
	if (!(m&1)){
		cout<<-1<<endl;
		return;
	}
	
	if (n==2&&m==1){
		cout<<"1 2"<<'\n'<<1<<'\n'<<1<<' '<<2;
		return;
	}
	
	set<int> res;
	for (int i=0;i<=20;i++)
		if (m&(1<<i)) res.insert((1<<i));
	if (*res.rbegin()>n){
		cout<<-1<<endl;
		return;
	}
	for (int i=1;i<=n;i++) if (res.count(i)) cout<<i<<' ';
	for (int i=1;i<=n;i++) if (!res.count(i)) cout<<i<<' ';
	if (res.size()==n){
		cout<<'\n'<<res.size()<<'\n';
		for (int i=1;i<=res.size();i++) cout<<i<<' '<<i<<'\n';	
	}else{
		cout<<'\n'<<res.size()+1<<'\n';
		for (int i=1;i<=res.size();i++) cout<<i<<' '<<i<<'\n';
		cout<<res.size()+1<<' '<<n<<'\n';
	}
	
}

二进制拆位,将 \(m\) 拆分为多个 \(2\) 的整数次幂构成的数,将这些数单独拿出来构成一个部分

排列中剩余的数构成单独的一个部分,这些剩下的数的 \(\mathrm{gcd}\) 一定为 \(1\)

并且因为任意两个奇偶数的 \(\mathrm{gcd}\) 都为 \(1\) ,那么给定的 \(m\) 一定不能为偶数,因为 \(1\) 需要被或上

注意 \(n=2,m=1\) 时需要特判

E:
题目大意:

image-20250725185505662

void solve(){
	int n;
	cin>>n;
	vector<pair<double,double>> p(n);
	for (int i=0;i<n;i++)
		cin>>p[i].first>>p[i].second;
	vector<double> d(n);
	for (int i=0;i<n-1;i++)
		d[i]=sqrt((p[i+1].first-p[i].first)*(p[i+1].first-p[i].first)+
		(p[i+1].second-p[i].second)*(p[i+1].second-p[i].second));
	
	const double ln2=log(2)/log(2.718281828);
	
	auto judge=[&](double mid,double dis){
		double f=2.0-2*dis*ln2/pow(2,mid);
		return f<0;
	};
	
	auto makef=[&](double k,double dis){
		double res=2*k+2*dis/pow(2,k);
		return res;
	};
	
	vector<double> vk;
	for (int i=0;i<n-1;i++){
		double l=0,r=10;
		while (r-l>0.000001){
			double mid=(l+r)/2;
			if (judge(mid,d[i])) l=mid;
			else r=mid;
		}
		vk.push_back(l);
	}
	double ans=0;
	for (int i=0;i<n-1;i++)
		ans+=makef(vk[i],d[i]);
	printf("%lf",ans);
}

\(t_i=2k^i+2e_i/2^{k_i}\) ,需要使得 \(t_i\) 最小化。不难看出这时一个单谷函数,所以利用三分或者求导后计算极值点

\[\frac{\mathrm{d} t_i}{\mathrm{d} k_i}=2-\frac{2\ln 2\cdot e_i}{2^{k_i}} \]

对于每个地点之间的欧式距离 \(e_i\) ,都利用二分计算 \(0\) 点,这个点一定是原函数的极小值点,最后累加答案即可

F:

题目大意:

image-20250725190127671

const int N=1e6+10;

LL ksm(LL a,LL b,LL p){
	LL res=1;
	while (b){
		if (b&1) res=res*a%p;
		a=a*a%p;
		b>>=1;
	}
	return res;
}

void solve(){
	vector<LL> c(N);
	LL base,mod;
	cin>>base>>c[0]>>mod;
	map<LL,int> mp;
	mp[c[0]]=0;
	int st,ed;
	for (int i=1;i<N;i++){
		c[i]=ksm(base%mod,c[i-1],mod);
		if (mp.count(c[i])){
			st=mp[c[i]];
			ed=i;
			break;
		}
		mp[c[i]]=i;
	}
	
	LL lamd=ed-st;
	vector<LL> loop;
	loop.push_back(0);
	for (int i=st;i<ed;i++)
		loop.push_back(c[i]);
		
	vector<LL> preloop(loop);
	for (int i=1;i<preloop.size();i++)
		preloop[i]=(preloop[i-1]+loop[i])%mod;
		
	vector<LL> prec(max(1,st));
	prec[0]=0;
	for (int i=1;i<st;i++)
		prec[i]=(prec[i-1]+c[i])%mod;
	
	int q;
	cin>>q;
	while (q--){
		LL k;
		cin>>k;
		LL ans=(st==0?-c[0]:0);
		if (k<st){
			ans=(ans+prec[k]+mod)%mod;
			cout<<ans<<endl;
			continue;
		}
		LL cslt=(k-st+1)/lamd%mod;
		LL rmde=(k-st+1)%lamd%mod;
		LL sum=cslt*preloop.back()%mod+preloop[rmde];
		ans=(ans+(prec.back()+sum%mod)%mod+mod)%mod;
		cout<<ans<<endl;
	}
}

因为 \(mod\in[1,10^6]\) ,说明在可以接受的范围内存在循环

找到循环后计算循环内和循环前两部分的前缀和(循环可能从某一位才开始),注意当循环从 \(0\) 就开始时答案需要多减去一个 \(c_0\)

因为需要计算的是 \(\sum_{i=1}^k c_i\) ,特别的,因为可能循环节的长度比较小而 \(k\) 很大,那么计算有多少个完整的循环时就需要取模

posted @ 2025-07-27 18:44  才瓯  阅读(5)  评论(0)    收藏  举报