首页 > 其他分享 >Codeforces Round #833 (Div. 2)(持续更新)

Codeforces Round #833 (Div. 2)(持续更新)

时间:2022-11-14 21:33:45浏览次数:52  
标签:833 int top Codeforces ans Div include RI define

Preface

我是大FW,B因为本地调试的时候把数组大小改成200忘记该回去了浪费了很多时间和罚时

C刚开始也没想清楚WA了两发心态爆炸,然后D其实想出了一种做法但是心态崩了就没写了

又是掉分我感觉有点难顶


A. The Ultimate Square

一个SB题给我做的巨蠢,直接输出\(\lceil\frac{n}{2}\rceil\)即可,但是我写的是个什么鬼我也不知道

#include<cstdio>
#include<cmath>
#define RI register int
#define CI const int&
using namespace std;
const int N=10005;
int t,n;
int main()
{
	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
	for (scanf("%d",&t);t;--t)
	scanf("%d",&n),printf("%d\n",(int)sqrt(1LL*n/2*(n/2+1)+(n&1?n+1>>1:0)));
	return 0;
}

B. Diverse Substrings

因为数的种类只有10种,根据抽屉原理,一个区间的长度最多为\(100\),因此直接暴力做即可

#include<cstdio>
#include<iostream>
#define RI register int
#define CI const int&
using namespace std;
const int N=100005;
int t,n,c[10],ans; char s[N];
int main()
{
	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
	for (scanf("%d",&t);t;--t)
	{
		RI i,j; for (scanf("%d%s",&n,s+1),ans=0,i=1;i<=n;++i)
		{
			for (j=0;j<10;++j) c[j]=0; int num=0,mx=0;
			for (j=i;j<=n;++j)
			{
				if (!c[s[j]-'0']) ++num; if (++c[s[j]-'0']>mx) mx=c[s[j]-'0'];
				if (mx<=num) ++ans; else if (mx>10) break;
			}
		}
		printf("%d\n",ans);
	}
	return 0;
}

C. Zero-Sum Prefixes

首先求出原序列的前缀和\(pfx\),考虑被\(0\)分开的每段区间,不难发现这个区间前面的\(0\)改成这个区间里出现次数最多的\(pfx\)即可

但是要注意开头的那个前面没有\(0\)的区间的情况要特别考虑,以及最后留下的一个单独的\(0\)结尾的情况

#include<cstdio>
#include<map>
#include<iostream>
#define RI register int
#define CI const int&
using namespace std;
int t,n,x,ans; map <long long,int> c;
inline void calc(int mx=0)
{
	for (auto v:c) mx=max(mx,(v.first?0:1)+v.second); ans+=mx;
}
int main()
{
	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
	for (scanf("%d",&t);t;--t)
	{
		RI i; long long pfx=0,lst=0; bool flag=0;
		for (scanf("%d",&n),ans=0,i=1;i<=n;++i)
		{
			scanf("%d",&x);
			if (!x) calc(),c.clear(),c[0]=pfx=0,flag=1; else
			{
				if (!flag)
				{
					if (pfx+=x,!pfx) ++ans;
				} else ++c[pfx+=x];
			}
		}
		calc(); printf("%d\n",ans); c.clear();
	}
	return 0;
}

D. ConstructOR

比赛的时候想了个算法以为是假的就没写,后来发现是对的(虽然我不会证正确性)

就是先考虑\(x\)的后\(30\)位,我们令\(x=a|b\),这样两个数的限制就变成一个了,记\(y=a|b\bmod d\)

接下来考虑前\(30\)位,相当于解方程\(2^{30}\times x'=d-y\pmod d\),直接上扩欧即可,代码我没写

考虑一种科学的做法,我们发现若\(a,b\)中有一个为奇数,而\(d\)为偶数时显然是无解的

否则说明\(a,b,d\)最低位都是\(0\),原问题转化为\(\frac{a}{2},\frac{b}{2},\frac{d}{2}\)之间的问题

因此我们设\(\operatorname{LSB}(x)\)表示\(x\)的二进制表示中最低位的\(1\)出现的位置,则\(\min(\operatorname{LSB}(a),\operatorname{LSB}(b))<\operatorname{LSB}(d)\)时无解

考虑有解的情况,我们从低到高考虑每一个\(x\)为\(0\)而\(d\)为\(1\)的位,把答案加上\(d\times 2^k\)即可(\(k\)为当前位与\(\operatorname{LSB}(d)\)的差值)

#include<cstdio>
#define int long long
#define RI register int
#define CI const int&
using namespace std;
int t,a,b,d;
signed main()
{
	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
	for (scanf("%lld",&t);t;--t)
	{
		RI i; bool flag=1; int lsb;
		for (scanf("%lld%lld%lld",&a,&b,&d),i=0;i<30;++i)
		{
			if ((d>>i)&1) { lsb=i; break; }
			if (((a|b)>>i)&1) { flag=0; break; }
		}
		if (!flag) { puts("-1"); continue; }
		int ans=0; for (i=lsb;i<30;++i)
		if ((((a|b)>>i)&1)&&!((ans>>i)&1)) ans+=d<<(i-lsb);
		printf("%lld\n",ans); 
	}
	return 0;
}

E. Yet Another Array Counting Problem

论你能不能想到笛卡尔树

今天补题的时候刚打开Tutorial结果看到笛卡尔树就知道怎么做了

原来的题目要求就是\(a,b\)的笛卡尔树同构,直接来个DP,设\(f_{i,j}\)表示树上点\(i\)的权值为\(j\)时的方案数

转移的话设\(g_{i,j}=\sum_{k\le j} f_{i,k}\),则\(f_{i,j}=g_{lson_i,j-1}\times g_{rson_i,j}\),注意左子树因为出现在\(i\)前面因此不能等于\(i\),而右子树就可以等于

#include<cstdio>
#include<vector>
#define RI register int
#define CI const int&
using namespace std;
const int N=200005,mod=1e9+7;
int t,n,m,a[N]; vector <int> f[N];
class Cartesian_tree
{
	private:
		int ch[N][2],stk[N],top;
		#define lc(x) ch[x][0]
		#define rc(x) ch[x][1]
	public:
		int rt;
		inline void build(void)
		{
			RI i; for (top=stk[1]=0,i=1;i<=n;++i)
			{
				lc(i)=rc(i)=0; while (top&&a[i]>a[stk[top]]) --top;
				if (top) lc(i)=rc(stk[top]),rc(stk[top])=i; else lc(i)=stk[1]; stk[++top]=i;
			}
			for (rt=stk[1],i=0;i<=m;++i) f[0][i]=1;
		}
		inline void DP(CI now)
		{
			if (!now) return; DP(lc(now)); DP(rc(now)); for (RI i=1;i<=m;++i)
			f[now][i]=1LL*f[lc(now)][i-1]*f[rc(now)][i]%mod,(f[now][i]+=f[now][i-1])%=mod;
		}
		#undef lc
		#undef rc
}CT;
int main()
{
	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
	for (scanf("%d",&t);t;--t)
	{
		RI i,j; for (scanf("%d%d",&n,&m),i=1;i<=n;++i) scanf("%d",&a[i]);
		for (i=0;i<=n;++i) for (f[i].resize(m+1),j=0;j<=m;++j) f[i][j]=0;
		CT.build(); CT.DP(CT.rt); printf("%d\n",f[CT.rt][m]);
	}
}

标签:833,int,top,Codeforces,ans,Div,include,RI,define
From: https://www.cnblogs.com/cjjsb/p/16890479.html

相关文章

  • Educational Codeforces Round 35 (Rated for Div. 2) F. Tree Destruction(树的直径/
    题目大意是给定一棵树,每次选择两个叶子将其删除,同时将两个叶子之间的简单路径长度加到答案上,找到一种方案使答案最大化,并输出删除的顺序。首先有一个结论是,距离树上某个节......
  • CF1748B Diverse Substrings
    题链:cfluogu诈骗题。Description给你一个数字(\(0\sim9\))组成的字串,问有多少个子串满足:不同数字种类数不少于相同数字的最多出现次数。Analysis暴力思路很好想其实......
  • Codeforces 722 F Cyclic Cipher 题解 (同余方程,two-pointers)
    题目链接前两天做过一个题意类似但做法不类似的题在这里首先做这道题需要一个结论:(一元)同余方程组有解的充要条件是方程组中的所有方程两两联立有解。证明两个同......
  • Codeforces 833 题解
    A\(n\)是奇数时恰好可以用完,\(n\)是偶数时多出来的一块没用,所以直接输出\((n+1)/2\)即可。B每个字符出现次数都小于等于字符总数,令\(\Sigma\)是字符集大小,那显然......
  • Codeforces Round #833 (Div. 2) A--B
    A思路:直接盲猜x/2上取整。应该写成(x+1)/2最好#include<bits/stdc++.h>#defineendl'\n'usingnamespacestd;voids(){intn;cin>>n;cout<<(n+1)/2<<......
  • 833——B题题解
    题目链接题目大意:给一串字符串(只包含0~9),定义一个最优子串的定义:如果该子串同字符种类数大于最最多字符出现数,那么这个子串可以被称为最优子串。解题思路:大眼一看这个数......
  • 833(DIV2)——C题题解
    题目链接题目大意:给定n个数,你可以对数值为0的数改变其为任意值,问最后前缀和为0的个数的最大值。思路:这题比较可惜,自己的思路没有问题,但是他少了一些东西。对数组进行前......
  • [VP]Codeforces Round #678 (Div. 2)
    诈骗题专场A.Reorder题意:给你一个长度为\(n\)的数组\(a\),问是否可以把这个重新排序后,使得\[\sum\limits^{n}_{i=1}\sum\limits^{n}_{j=i}\dfrac{a_j}{j}=m\]解法:......
  • Codeforces Round #786 (Div. 3) 补题记录
    小结:A,B,F切,C没写1ll对照样例才发现,E,G对照样例过,D对照样例+看了其他人代码(主要急于看后面的题,能调出来的但偷懒了。CF1674ANumberTransformation考虑若\(y\)......
  • HTML学生个人网站作业设计:旅游景点网站设计——北京故宫(9页) HTML+CSS+JavaScript 简
    ......