首页 > 其他分享 >周赛_CF758+CF760

周赛_CF758+CF760

时间:2023-03-18 16:58:05浏览次数:29  
标签:周赛 string int max ll CF758 read ans CF760

第一题感觉就是先求gcd载检查是否正确。不过“检查”这一步骤我不是很会。

constexpr int N=1e2+2;
ll a[N];
#define fail do{puts("0");goto loop;}while(0)
int main(){
for(int t=read();t--;){
	int n=read();
	for(int i=0;i<n;++i)a[i]=read();
	vector<ll> g(a,a+2);
    for(int i = 0; i < n; i++)
    {
        g[i % 2] = __gcd(g[i % 2], a[i]);
    }  
	/*ll odd=a[1],even=a[2];
	for(int i=3;i<=n;++i){
		if(i&1)
			odd=__gcd(odd,a[i]);
		else 
			even=__gcd(even,a[i]);
	}
	//printf("#odd %lld, even %lld\n",odd,even);
	
	if(odd==even)fail;
	else if(even==1){
		for(int i=2;i<=n;i+=2)
		if(a[i]%odd==0)fail;	
	}
	else if(odd==1){
		for(int i=1;i<=n;i+=2)
		if(a[i]%even==0)fail;
	}
	printf("%lld\n",max(odd,even));
	loop:;
	*/
	bool good[2]={1,1};
	for(int i=0;i<n;++i)
		good[i%2]=good[i%2]&&(a[i]%g[(i%2)^1]>0);
	ll ans=0;
	if(good[0])ans=max(ans,g[1]);
	if(good[1])ans=max(ans,g[0]);
	printf("%lld\n",ans);
}
	return 0;
}

B

构造题都是“想出来就赢了”。
先构造一上一下的许多交叉项来获取足够数量的max和min,再把剩下的数按顺序放在一端,以确保不会造成新的max或min。

constexpr int N=1e5+2;
#define fail do{puts("-1");goto loop;}while(0)
int p[N];
inline void build(int a,int b,int n){
	for(int i=1;i<n-a-b;++i)p[i]=i;
	for(int i=1,f=1;i<=a+b+1;++i,f^=1){
		p[i+(n-a-b)-1]=f?(n-i/2):(n-a-b-1+i/2);
	}
}
int main(){
for(int t=read();t--;){
	int n=read(),a=read(),b=read();
	if(a+b>n-2||abs(a-b)>1)fail;
	if(a>=b){
		build(a,b,n);
		for(int i=1;i<=n;++i)printf("%d ",p[i]);puts("");
	}
	else {
		build(b,a,n);
		for(int i=1;i<=n;++i)printf("%d ",n+1-p[i]);puts("");
	}
	loop:;
}
	return 0;
}

C

最大的k个一定要消去,然后还需要消除次大的k个,并且小的除以小的(按顺序分别除),以减少除出1的数量。
其实就是贪心。两个区间当中谁除以谁并不会影响剩下的元素的加和。

for(int t=read(),a[102];t--;){
	int n=read(),k=read(),ans=0;
	for(int i=0;i<n;++i)a[i]=read();
	sort(a,a+n);
	for(int i=0;i<n-2*k;++i)ans+=a[i];
	for(int i=0;i<k;++i)ans+=a[n-2*k+i]/a[n-k+i];
	printf("%d\n",ans);
}

D

解线性方程组。要求所有的解为正数。

constexpr int N=4e4+2;
#define fail do{puts("NO");goto loop;}while(0)
int a[N],b[N];

int main(){ // 解线性方程组
for(int t=read();t--;){
	ll n=read(),sumb=0,d=n*(n+1)/2,suma;
	for(int i=0;i<n;++i)sumb+=b[i]=read();
	if(sumb%d)fail;
	suma=sumb/d;
	for(int i = n-1; ~i; i--) {
        ll res = (b[i] - b[(i + 1) % n] + suma);
        if(res % n != 0 || res <= 0)fail;
        a[(i + 1) % n] = res / n;
    }
    puts("YES");
    for(int i=0; i<n; i++)printf("%d ",a[i]);
    puts("");
    loop:;
}
	return 0;
}

E

tarjan缩点后,入度为0的SCC里面的点全是赢家,其余都输。
可以证明,从x开始能跑通全图 等价于 x能跑到max{a}(这个点一定可以跑通全图)

可以找到max,从他开始跑反图,能到达的点即赢家。这等价于在0号SCC里找一个点开始跑反图,反图里面所有到达的点都是赢家。DFS、BFS都行。

由于只有2种边,也可以转成双指针,0个以上返祖边覆盖的极大子区间即一个SCC。如下图。然后依然找a最大的点所在的SCC。

constexpr int N=1e5+2;
int a[N],b[N],p[N];
vector<int> ve[N];
bool vis[N];
void dfs(int u){
	vis[u]=1;//printf("#dfs %d\n",u);
	for(auto&& v:ve[u])if(!vis[v])dfs(v);
}
int main(){
for(int t=read();t--;){
	int n=read(),maxi;
	
	for(int i=0,maxa=0;i<n;++i){
		a[p[i]=i]=read();
		if(maxa<a[i])maxa=a[i],maxi=i;
		ve[i].clear();
	}
	sort(p,p+n,[](int x,int y){return a[x]<a[y];});
	for(int i=0;i<n-1;++i)ve[p[i]].push_back(p[i+1]);
	
	for(int i=0;i<n;++i)b[p[i]=i]=read();
	sort(p,p+n,[](int x,int y){return b[x]<b[y];});
	for(int i=0;i<n-1;++i)ve[p[i]].push_back(p[i+1]);
	
	memset(vis,0,n+1);
	dfs(maxi);
	for(int i=0;i<n;++i)putchar('0'^vis[i]);
	puts("");
}
	return 0;
}

F

按照题意直接构造,然后把所有答案存储在set甚至hash_table中,最后检测y是否被算出来过即可。
有效的答案的长度不会超过y的长度,这就为中间的计算确定了边界。

以上是因为数据范围有限(1e18)。数据范围大一点的话就得换高效算法了。

inline string rev(string t){
    while(t.back() == '0') t.pop_back();
    reverse(t.begin(), t.end());
    return t;
}
string bin(int x){
	return x?bin(x/2)+string(1,char(x&1^'0')):"";
}
signed main(){
	//for(int i=1;i<=64;++i)cout<<bin(i)<<endl;
	int x=read(),y=read();
	set<string>used{bin(x)};
	queue<string>q;
	for(q.push(bin(x));!q.empty();){
		string k=q.front();
		q.pop();
		if(k.size()>65)continue;
		for(int i=0; i<2; i++){
            string kk=rev(k+string(1,char('0'^i)));
            if(!used.count(kk)){
                used.insert(kk);
                q.push(kk);
            }
        }
	}
	puts(used.count(bin(y))?"YES":"NO");
	return 0;
}

标签:周赛,string,int,max,ll,CF758,read,ans,CF760
From: https://www.cnblogs.com/quanqiutong-u1/p/17231159.html

相关文章

  • AcWing 第 93 场周赛 4868. 数字替换(dfs+剪枝)
    https://www.acwing.com/problem/content/4871/题目大意:给定两个整数n,x。(x为原始数据,n为需要我们把x变成的位数)可以对x进行任意次以下操作:选择x的一位数字y,将x替......
  • 2018年东北农业大学春季校赛(周赛训练)
    题解报告题解顺序不是原来比赛的题目顺序题目意思可以去原题了解基本的一些理解和问题都在注释中题目一:wyh的矩阵//思维题,找规律,考虑中点的性质。#include<cstd......
  • LeetCode 周赛 336,多少人直接 CV?
    本文已收录到AndroidFamily,技术和职场问题,请关注公众号[彭旭锐]提问。大家好,我是小彭。今天早上是LeetCode第336场周赛,你参加了吗?这场周赛整体质量比较高,但是最......
  • 2023学校周赛Round1 Div1
    \(A\)拿个栈模拟一下。\(B\)推一推式子,把\((\displaystyle\sum_{i=1}^{n}a_i)^3\)展开,会得到三种类型的式子,其中两个都是可以线性求出来的,第三个的6倍就是答案。\(C\)......
  • AcWing 第 94 场周赛 A B(最短路dij) C(最短路floyed)
    https://www.acwing.com/activity/content/competition/problem_list/2961/AcWing4870.装物品水题#include<bits/stdc++.h>usingnamespacestd;typedeflonglon......
  • AcWing94场周赛复盘
    快速手速题不能犹豫已知,每个背包最多可以装件物品。请你计算,要装下件物品最少需要多少个背包。输入格式一个整数。输出格式一个整数,表示所需背包的最少数量。数据范围......
  • 6317.统计美丽子数组的数目-336周赛
    统计美丽子数组的数目给你一个下标从0 开始的整数数组nums 。每次操作中,你可以:选择两个满足 0<=i,j<nums.length 的不同下标 i 和 j 。选择一个非负整数......
  • LeetCode 周赛 335,纯纯手速场!
    本文已收录到AndroidFamily,技术和职场问题,请关注公众号[彭旭锐]提问。大家好,我是小彭。昨晚是LeetCode第335场周赛,你参加了吗?这场周赛整体难度不高,有两道模板题......
  • [第335场周赛]质因数分解,多重背包
    喜提AK以及最佳排名:6307. 递枕头提示简单3相关企业​​n​​ 个人站成一排,按从 ​​1​​ 到 ​​n​​ 编号。最初,排在队首的第一个人拿着一个枕头。每秒钟,拿着枕头......
  • 力扣第335场周赛补题题解
    目录1.递枕头2.二叉树中的第K大层和3.分割数组使乘积互质4.获得分数的方法数1.递枕头classSolution{public:intpassThePillow(intn,inttime){......