首页 > 其他分享 >Codeforces Round #846 (Div. 2) 解题报告

Codeforces Round #846 (Div. 2) 解题报告

时间:2023-01-26 02:22:05浏览次数:73  
标签:846 cnt right int dfrac Codeforces MAXN Div left

Codeforces Round #846 (Div. 2) 解题报告

\(\text{By DaiRuiChen007}\)

Contest Link

A. Hayato and School

简单题,发现答案要么是一奇两偶、要么是三个奇数,分别考虑两种情况即可

时间复杂度 \(\Theta(n)\)

#include<bits/stdc++.h>
using namespace std;
const int MAXN=301;
int a[MAXN];
inline void solve() {
	int n;
	scanf("%d",&n);
	vector <int> cnt[2];
	for(int i=1;i<=n;++i) scanf("%d",&a[i]),cnt[a[i]%2].push_back(i);
	if((int)cnt[0].size()>=2&&(int)cnt[1].size()>=1) {
		printf("YES\n%d %d %d\n",cnt[0][0],cnt[0][1],cnt[1][0]);
	} else if((int)cnt[1].size()>=3) {
		printf("YES\n%d %d %d\n",cnt[1][0],cnt[1][1],cnt[1][2]);
	} else puts("NO");
}
signed main() {
	int T;
	scanf("%d",&T);
	while(T--) solve();
	return 0;
}

B. GCD Partition

注意到如果分成的 \(k>2\),那么把这些东西合成两段,其 \(\gcd\) 一定不会变小,因此只需要考虑 \(k=2\) 的情况,枚举断点暴力即可

时间复杂度 \(\Theta(n\log w)\),\(w\) 为 \(\sum a_i\) 的值域,瓶颈在求 \(n\) 次 \(\gcd\) 上

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int MAXN=2e5+1;
int a[MAXN],sum[MAXN];
inline int gcd(int a,int b) {
	if(!b) return a;
	return gcd(b,a%b);
}
inline void solve() {
	int n,ans=0;
	scanf("%lld",&n);
	for(int i=1;i<=n;++i) scanf("%lld",&a[i]),sum[i]=sum[i-1]+a[i];
	for(int i=1;i<n;++i) ans=max(ans,gcd(sum[i],sum[n]-sum[i]));
	printf("%lld\n",ans);
}
signed main() {
	int T;
	scanf("%lld",&T);
	while(T--) solve();
	return 0;
}

D. Bit Guessing Game

考虑这样的操作:

对于 \(n=2^k\) 的情况,操作 - 1 会使得 \(\operatorname{popcount}(n)\) 从 \(1\) 变成 \(k\)

同理,对于任意 \(n\),操作 - 1 会使得 \(\operatorname{popcount}(n)\) 增加 \(\operatorname{lowbit}(n)-1\)

同理,我们用类似这样的方法,根据 \(\operatorname{popcount}(n)\) 的变化量每一次都能求出 \(n\) 的下一个 \(1\) 位在哪里

每次询问找到一个 \(1\),总询问次数不超过 \(\log_2 n\) 次,满足要求

时间复杂度 \(\Theta(\log n)\)

#include<bits/stdc++.h>
using namespace std;
inline int read(int x) {
	cout<<"- "<<x<<endl;
	int ret; cin>>ret; return ret;
}
inline int bit(int x) { return 1<<x; }
inline void solve() {
	int tot;
	cin>>tot;
	int ans=0,lst=0,pre=tot;
	for(int i=1;i<=tot;++i) {
		int now=read(bit(lst));
		int nxt=lst+(now+1-pre);
		ans|=bit(nxt);
		lst=nxt+1,pre=now;
	}
	cout<<"! "<<ans<<endl;
}
signed main() {
	int T;
	cin>>T;
	while(T--) solve();
	return 0;
}

E. Josuke and Complete Graph

把条件转化成统计所有 \(k\) 使得存在 \(l\le x,y\le r\) 且 \(\gcd(x,y)=k,x\ne y\) 的 \(k\) 的数量

注意到只要 \([l,r]\) 中有至少 \(2\) 个 \(k\) 的倍数,那么 \(k\) 就满足要求

因此等价于统计所有 \(\left\lfloor \dfrac rk\right\rfloor-\left\lceil \dfrac lk\right\rceil+1\ge 2\) 的 \(k\) 的数量即可,这又可以等价于 \(\left\lfloor\dfrac rk\right\rfloor -\left\lfloor\dfrac{l-1}k\right\rfloor \ge 2\) 的 \(k\) 的数量

显然对 \(l-1\) 整除分块:

  • 对于所有 \(k\le\sqrt{l-1}\) 的 \(k\),暴力枚举并统计即可

  • 对于所有 \(k>\sqrt{l-1}\) 的 \(k\),枚举 \(\left\lfloor\dfrac {l-1}k\right\rfloor=i\),显然 \(i\) 的值域也是 \(\Theta(\sqrt l)\) 这一级别的

    那么我们要求:\(\left\lfloor\dfrac {l-1}k\right\rfloor=i,\left\lfloor\dfrac rk\right\rfloor\ge i+2\),简单拆开变形一下即可得到 \(\left\lceil\dfrac l{i+1}\right\rceil\le k\le\min\left\{\left\lfloor\dfrac{l-1}i\right\rfloor,\left\lfloor\dfrac r{i+2}\right\rfloor\right\}\),特判 \(i=0\) 的情况即可

注意特判 \(l=1\) 的情况,此时答案为 \(\left\lfloor\dfrac r2\right\rfloor\)

时间复杂度 \(\Theta(t\sqrt l)\)

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int INF=1e18;
inline void solve() {
	int l,r;
	scanf("%lld%lld",&l,&r);
	--l;
	if(l==0) {
		printf("%lld\n",r/2);
		return ;
	}
	int ans=0,d=0;
	for(int k=1;k*k<=l;++k) {
		d=(l/k);
		if((r/k)-(l/k)>=2) ++ans;
	}
	for(int i=0;i<d;++i) {
		int L=(l+i+1)/(i+1);
		int R=r/(i+2);
		if(i>0) R=min(R,l/i);
		if(L<=R) ans+=R-L+1;
	}
	printf("%lld\n",ans);
}
signed main() {
	int T;
	scanf("%lld",&T);
	while(T--) solve();
	return 0;
}

F. Three Chairs

看到 \(\gcd(\max\{a_i,a_j,a_k\},\min\{a_i,a_j,a_k\})=1\) 第一时间想到反演

发现对形如 \(d\mid \gcd(\max\{a_i,a_j,a_k\},\min\{a_i,a_j,a_k\})\) 这样的 \((i,j,k)\) 进行计数很好做:

我们只需要先对 \(a_i\) 排序,再把所有 \(d\mid a_i\) 的 \(i\) 按顺序加入序列 \(\{k_i\}\),然后在 \(\{k_i\}\) 中任选两个做 \(\min,\max\),然后枚举中间数即可,即统计 \(\{k_i\}\)中所有 \(k_i>k_j\) 的 \(k_i-k_j-1\) 之和

那么我们记 \(f(d)\) 表示所有满足 \(\gcd(\max\{a_i,a_j,a_k\},\min\{a_i,a_j,a_k\})=d\) 的 \((i,j,k)\) 的数量,\(g(d)\) 表示所有满足 \(d\mid \gcd(\max\{a_i,a_j,a_k\},\min\{a_i,a_j,a_k\})\) 的 \((i,j,k)\) 的数量

进行对 \(f,g\) 莫比乌斯反演:\(g(n)=\sum_{n\mid d} f(d)\implies f(n)=\sum_{n\mid d} g(d)\times \mu\left(\dfrac dn\right)\)

而我们要求的就是 \(f(1)\) 的值,按照上述过程计算即可,注意实现的常数

时间复杂度 \(\Theta(n\sqrt w)\),其中 \(w\) 是 \(a_i\) 的值域

#include<bits/stdc++.h>
#define ll long long
#pragma GCC target("sse,sse2,sse3,sse4,popcnt,abm,mmx,avx,avx2")
using namespace std;
const int MAXN=3e5+1;
int a[MAXN],mu[MAXN],n;
ll ans,sum[MAXN];
int cnt[MAXN];
bool mark[MAXN];
vector <int> primes;
inline void solve(int p,int x) {
	if(mu[p]==0) return ;
	ans+=(ll)mu[p]*(ll)((ll)(x-1)*(ll)cnt[p]-sum[p]);
	sum[p]+=(ll)x,++cnt[p];
}
signed main() {
	for(int i=1;i<MAXN;++i) mu[i]=1;
	for(int i=2;i<MAXN;++i) {
		if(!mark[i]) mu[i]=-1,primes.push_back(i);
		for(int p:primes) {
			if(i*p>=MAXN) break;
			mark[i*p]=true,mu[i*p]=-mu[i];
			if(i%p==0) {
				mu[i*p]=0;
				break;
			}
		}
	}
	scanf("%d",&n);
	for(int i=1;i<=n;++i) scanf("%d",&a[i]);
	sort(a+1,a+n+1);
	for(int i=1;i<=n;++i) {
		for(int j=1;j*j<=a[i];++j) {
			if(a[i]%j==0) {
				solve(j,i);
				if(j*j!=a[i]) solve(a[i]/j,i);
			}
		}
	}
	printf("%lld\n",ans);
	return 0;
}

标签:846,cnt,right,int,dfrac,Codeforces,MAXN,Div,left
From: https://www.cnblogs.com/DaiRuiChen007/p/17067528.html

相关文章

  • Codeforces Round #661 (Div. 3) D. Binary String To Subsequences(贪心/思维)
    https://codeforces.com/contest/1399/problem/D题目大意:长度为n的字符串s只由0和1组成。我们要把s分成最小数量的子序列,使得每一个子序列看起来像“010101...”或......
  • Educational Codeforces Round 142 (Rated for Div. 2) A-D
    比赛链接A题解知识点:贪心。代码#include<bits/stdc++.h>usingnamespacestd;usingll=longlong;boolsolve(){intn;cin>>n;intcnt=0;......
  • Codeforces Round #845----C
    题目:Problem-C-Codeforces题解:使用双指针。枚举l,寻找最小的r使条件成立。代码:#include<bits/stdc++.h>usingnamespacestd;voidsolve(){ intn,m; cin>......
  • CF1792 D. Fixed Prefix Permutations : Educational Codeforces Round 142 (Rated fo
    给出n个长度为m的排列(a1,a2,a3,...,an)定义一个操作 r=ai•aj:r[k]=a[j][a[i][k]]定义一个排列(p1,p2,...,pn)的beauty为最大的k,使得p[1]=1,p[2]=2,..,p[k......
  • CF Educational Round 142 (Rated for div2) 题解
    A注意到除了血量为\(1\)的怪物,其余的怪物直接斩杀是更合理的。所以只要统计血量为\(1\)的怪物的个数即可。#include<cstdio>voidsolve(){ intn;scanf("%d",......
  • Codeforces Round #822 (Div. 2) D
    链接:https://codeforces.com/problemset/problem/1734/E题意,给定n,b[1~n],求一个nn矩阵,满足a[i][i]=b[i],且对于r1<r2,c1<c2,a[r1][c1]+a[r2][c2]!=a[r1][c2]+a[r2][c1](m......
  • CodeForces-907#B 题解
    正文设数组\(c_{x,y,i,j}\)代表\((x,y)\)位置的大格子中\((i,j)\)位置的小格子。很显然,输入中字符的输入顺序是要调整的,实际的顺序是\(x,i,y,j\)。对于输入的\(......
  • Codeforces Round #845 (Div. 2) and ByteRace 2023 A-D
    CodeforcesRound#845(Div.2)andByteRace2023A-DA.EverybodyLikesGoodArrays!题意:对给定数组进行操作:删除相邻两项,替换为两项的乘积,使得该数组奇偶相间。......
  • JavaScript: div,textarea set or get value
    <!doctypehtml><html><head><metacharset="utf-8"><metaname="viewport"content="width=device-width,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0,u......
  • CF Div2 Round 845
    A注意到奇数和奇数的乘积仍是奇数。偶数和偶数的乘积仍是偶数。所以答案就是\(n\)减去奇偶连续段段个数。#include<cstdio>#include<vector>usingnamespacestd......