文章目录

传送门

又一场原地爆炸的比赛。

A题

传送门 简单思维题

题意:给一个4∗44*44∗4的格子图和一个01串,你要根据01串放1∗21*21∗2的木块,如果是0就竖放一个,是1就横放一个,一行或者一列满了可以直接消掉。

现在让你每次输出放下木块的坐标,并保证所有操作中没有木块相交。


思路:

可以直接按照自己的思路模拟然后我这个sb想了好久用什么策略

下来之后突然想到一个更简单的做法,我们保证如果竖放先放(1,1)(1,1)(1,1),如果横放先放(4,4)(4,4)(4,4),这样接下来无论是横放还是竖放都会消掉之前放过的一个。

比赛代码(丑:

#include<bits/stdc++.h>
#define ri register int
#define fi first
#define se second
using namespace std;
inline int read(){
	int ans=0;
	char ch=getchar();
	while(!isdigit(ch))ch=getchar();
	while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
	return ans;
}
char s[1005];
int n,vis[5][5];
inline void update(){
	for(ri i=1;i<=4;++i)if(vis[i][1]&&vis[i][2]&&vis[i][3]&&vis[i][4])vis[i][1]=vis[i][2]=vis[i][3]=vis[i][4]=0;
	for(ri i=1;i<=4;++i)if(vis[1][i]&&vis[2][i]&&vis[3][i]&&vis[4][i])vis[1][i]=vis[2][i]=vis[3][i]=vis[4][i]=0;
}
inline void find(int type){
	if(!type){
		for(ri j=1;j<=4;++j)for(ri i=1;i<=3;++i){
			if(!vis[i][j]&&!vis[i+1][j]){
				vis[i][j]=vis[i+1][j]=1;
				cout<<i<<' '<<j<<'\n';
				return update();
			}
		}
	}
	else{
		for(ri i=1;i<=4;++i)for(ri j=1;j<=3;++j){
			if(!vis[i][j]&&!vis[i][j+1]){
				vis[i][j]=vis[i][j+1]=1;
				cout<<i<<' '<<j<<'\n';
				return update();
			}
		}
	}
}
int main(){
	scanf("%s",s+1),n=strlen(s+1);
	for(ri i=1;i<=n;++i)find(s[i]-'0');
	return 0;
}

B题

传送门 二分答案

题意简述:你需要通过不超过60次询问来猜一个数a,a≤1e9a,a\le1e9a,a≤1e9,每次可以问两个数x,yx,yx,y,如果(xmod&ThinSpace;&ThinSpace;a)≥(ymod&ThinSpace;&ThinSpace;a)(x\mod a)\ge (y\mod a)(xmoda)≥(ymoda)会返回000否则返回111


思路:

我们考虑倍增求出aaa的范围然后再二分求aaa的准确值。

最开始先让x=0,y=1x=0,y=1x=0,y=1然后问,如果返回111就说明aaa不在区间(x,y](x,y](x,y]里,那么令x=y,y=y∗2+1x=y,y=y*2+1x=y,y=y∗2+1继续问下去知道返回000位置。

返回000时说明aaa的取值在(x,y](x,y](x,y]之间,那么我们二分aaa的值一直问x,midx,midx,mid来缩小范围即可。

代码:

#include<bits/stdc++.h>
#define ri register int
#define fi first
#define se second
using namespace std;
inline int read(){
	int ans=0;
	char ch=getchar();
	while(!isdigit(ch))ch=getchar();
	while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
	return ans;
}
char s[6];
typedef long long ll;
int main(){
	while(scanf("%s",s)){
		if(s[0]=='e')break;
		if(s[0]=='m')break;
		ll x=0,y=1;
		while(cout<<"? "<<x<<' '<<y<<endl,fflush(stdout),scanf("%s",s),s[0]=='y'){
			x=y,y=x*2+1;
		}
		if(s[0]=='e')break;
		ll l=x+1,r=y,ans=y;
		while(l<=r){
			ll mid=l+r>>1;
			bool f;
			cout<<"? "<<x<<' '<<mid<<endl,fflush(stdout),scanf("%s",s),f=s[0]=='x';
			if(s[0]=='e')break;
			if(f)r=mid-1,ans=mid;
			else l=mid+1;
		}
		cout<<"! "<<ans<<endl;
		fflush(stdout);
	}
	return 0;
}

C题

传送门 结论+构造

题意简述:给一张无重边自环的无向图,每个点度数至少为3,现在给出kkk,要求你构造出以下两类答案中的任意一种:

  1. 找到一条路径,使得其长度≥nk\ge\frac nk≥kn​
  2. 找到kkk个环,使得每个环长度至少为333且不为333的倍数,且每个环中至少有一个点在所有输出的环中只出现过一次。

思路:

我们先dfsdfsdfs构造出图的一个生成树,这个时候如果闲的胃疼可以求一遍直径去构造第一类答案,也可以直接枚举每个点的深度来判断能不能简单构造,如果不行就直接去构造多个环的答案。

然后考虑如何构造出多个环的答案,在生成树上面每个数的深度都不能满足条件的时候说明至少有kkk个 叶子结点,由于每个点度数至少为333,因此这个叶子结点除了连接父亲的树边以外还存在跟自己祖先连接的两条非树边 注意这里说的是祖先,因为如果不是祖先的话dfs的时候会走过去,它就不是叶子节点了

然后说明至少有两个环,且这个叶子结点可以当做那个在所有环中只出现过一次的特殊点。

然后可以用如下方法构造答案。

  1. 两个环中至少有一个长度不是333的倍数,直接输出这个环。
  2. 两个环的长度都是333的倍数,那么设离当前叶子结点近的点是yyy,原的是xxx,叶子结点是zzz,我们把y−&gt;xy-&gt;xy−>x路径上所有点和zzz拿来构造成一个环,这个环的长度是3k+13k+13k+1满足题意。

代码(略丑:

#include<bits/stdc++.h>
#define ri register int
using namespace std;
inline int read(){
	int ans=0;
	char ch=getchar();
	while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
	return ans;
}
const int N=250005,M=5e5+5;
int n,m,k,dep[N],fa[N];
bool leaf[N],vis[N];
vector<int>e[N];
void dfs(int p){
	leaf[p]=vis[p]=1;
	for(ri i=0,v;i<e[p].size();++i){
		if(vis[v=e[p][i]])continue;
		leaf[p]=0,dep[v]=dep[p]+1,fa[v]=p,dfs(v);
	}
}
int main(){
	n=read(),m=read(),k=read();
	for(ri i=1,u,v;i<=m;++i)u=read(),v=read(),e[u].push_back(v),e[v].push_back(u);
	dep[1]=1,dfs(1);
	int tmp=(n+k-1)/k;
	for(ri i=1;i<=n;++i){
		if(dep[i]>=tmp){
			puts("PATH");
			printf("%d\n",dep[i]);
			while(i){
				printf("%d ",i);
				i=fa[i];
			}
			return 0;
		}
	}
	puts("CYCLES");
	vector<int>pos;
	for(ri i=1;i<=n&&pos.size()<k;++i)if(leaf[i])pos.push_back(i);
	for(ri i=1,p;i<=k;++i){
		bool f=0;
		p=pos[i-1];
		for(ri j=0,v;j<e[p].size();++j){
			if((v=e[p][j])!=fa[p]&&(dep[p]-dep[v]+1)%3){
				printf("%d\n",dep[p]-dep[v]+1),f=1;
				while(fa[p]!=fa[v]){
					printf("%d ",p);
					p=fa[p];
				}
				printf("%d",p);
				puts("");
				break;
			}
		}
		if(f)continue;
		vector<int>bad;
		for(ri j=0,v;j<e[p].size()&&bad.size()<2;++j)if((v=e[p][j])!=fa[p])bad.push_back(v);
		int x=bad[0],y=bad[1];
		if(dep[x]>dep[y])swap(x,y);
		printf("%d\n",dep[y]-dep[x]+2);
		printf("%d ",p);
		while(fa[x]!=fa[y]){
			printf("%d ",y);
			y=fa[y];
		}
		printf("%d",y);
		puts("");
	}
	return 0;
}

D题

传送门 状压dp好题

题意简述:给nnn个二元组和一个kkk。

二元组(ai,ei)(a_i,e_i)(ai​,ei​)表示第iii个位置的权值是aia_iai​,贡献是eie_iei​。

现在对于每个位置可以让它的权值除以它自己一个不超过kkk的约数,要求从nnn个数中选择若干个数出来,使得它们的权值在除以约数过后的gcdgcdgcd为111,花费的代价是选出来的选择数的个数乘上选出来的所有数的贡献和。

数据范围:n≤1e5,k,ai≤1e12n\le1e5,k,a_i\le1e12n≤1e5,k,ai​≤1e12


思路:

考虑到gcdgcdgcd的范围也是[1,1e12][1,1e12][1,1e12],不难证明这个gcdgcdgcd最多有不超过121212个不同的质因子。

先思考一个问题:怎么去除自己的约束最优?

我们先令gcd=a1p1a2p2...akpkgcd=a_1^{p_1}a_2{p^2}...a_k^{p_k}gcd=a1p1​​a2​p2...akpk​​

显然对于一个要计入答案的数valvalval,只用关心它和gcdgcdgcd都有的质因数。

所以令val=t∗a1q1a2q2...akqkval=t*a_1^{q_1}a_2^{q_2}...a_k^{q_k}val=t∗a1q1​​a2q2​​...akqk​​,其中(t,a1)=(t,a2)=...=(t,ak)=1(t,a_1)=(t,a_2)=...=(t,a_k)=1(t,a1​)=(t,a2​)=...=(t,ak​)=1

那么对于这个数,我们选择它肯定就要它自己使得若干个幂次不为000的质数幂全部去掉,否则不如不选它,即去掉a1q1,a2q2,...,akqka_1^{q_1},a_2^{q_2},...,a_k^{q_k}a1q1​​,a2q2​​,...,akqk​​中的至少一个 这里去掉的意思指的是用除法除掉,这样之后取gcd的时候如果选这个数这个被除掉的质数幂就不会算进去

这样一来,我们选出来的每个数至少会去掉一种之前没出现过的质数幂,因此最多选择不超过12个数就能够使得它们在除去质因子之后的gcdgcdgcd为1。

于是可以设计状态fi,jf_{i,j}fi,j​表示现在已经去除的质因子的集合为iii,用了jjj个数。

考虑先把所有相同的数并在一起(因为它们分解之后也是相同的)

转移的话可以先对于每个数预处理出另外一个dpdpdp数组ggg,gig_igi​表示对于这个数要使得被除去的质数幂状态为iii所需的最小这个数的个数(因为把相同的并在一起所以每个数的个数不一定是1)。

然后再枚举子集转移就行了。

细节较多。

代码:

#include<bits/stdc++.h>
#define ri register int
using namespace std;
typedef long long ll;
inline ll read(){
	ll ans=0;
	char ch=getchar();
	while(!isdigit(ch))ch=getchar();
	while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
	return ans;
}
inline map<ll,int> solve(ll x){
	map<ll,int>ret;
	ret.clear();
	for(ll i=2;i*i<=x;++i)while(x%i==0)x/=i,++ret[i];
	if(x^1)++ret[x];
	return ret;
}
const ll inf=1e18;
const int N=(1<<12)+5,M=13,K=1e6+5;
int n,m;
ll k,a[K],b[K],gc,res=inf;
int main(){
	n=read(),k=read(),gc=0;
	for(ri i=1;i<=n;++i)gc=__gcd(a[i]=read(),gc);
	for(ri i=1;i<=n;++i)b[i]=read();
	map<ll,int>fac=solve(gc);
	vector<ll>divv;
	for(map<ll,int>::iterator it=fac.begin();it!=fac.end();++it)divv.push_back(it->first);
	m=divv.size();
	vector<ll>v(m);
	map<vector<ll>,vector<ll> >mp;
	for(ri i=1;i<=n;++i){
		for(ri j=0;j<m;++j){
			v[j]=1;
			while(a[i]%divv[j]==0)a[i]/=divv[j],v[j]*=divv[j];
		}
		mp[v].push_back(b[i]);
	}
	vector<vector<ll> >f(1<<m,vector<ll>(m+1,inf));
	f[0][0]=0;
	for(map<vector<ll>,vector<ll> >::iterator it=mp.begin();it!=mp.end();++it){
		vector<ll>mul=it->first,sum=it->second,g(1<<m,inf);
		sort(sum.begin(),sum.end());
		for(ri i=1;i<sum.size();++i)sum[i]+=sum[i-1];
		for(ri i=0;i<(1<<m);++i){
			ll mult=1;
			for(ri j=0;j<m;++j)if((i>>j)&1)mult*=mul[j];
			if(mult<=k)g[i]=1;
		}
		for(ri i=0;i<(1<<m);++i)for(ri j=i;j;j=(j-1)&i){if(j==i)continue;g[i]=min(g[i],g[i^j]+g[j]);}
		for(ri i=(1<<m)-1;~i;--i)for(ri j=i;j;j=(j-1)&i){
			if(g[j]>sum.size())continue;
			for(ll k=0;g[j]+k<=m;++k)f[i][k+g[j]]=min(f[i][k+g[j]],f[i^j][k]+sum[g[j]-1]);
		}
	}
	for(ri i=0;i<=m;++i)if(f[(1<<m)-1][i]^inf)res=min(res,f[(1<<m)-1][i]*i);
	cout<<(res==inf?-1:res);
	return 0;
}

Codeforces 1103 简要题解(持续更新)的更多相关文章

  1. Codeforces 863 简要题解

    文章目录 A题 B题 C题 D题 E题 F题 G题 传送门 简要题解?因为最后一题太毒不想写了所以其实是部分题解... A题 传送门 题意简述:给你一个数,问你能不能通过加前导000使其成为一个回文数 ...

  2. LeetCode python实现题解(持续更新)

    目录 LeetCode Python实现算法简介 0001 两数之和 0002 两数相加 0003 无重复字符的最长子串 0004 寻找两个有序数组的中位数 0005 最长回文子串 0006 Z字型变 ...

  3. Codeforces 1098 简要题解

    文章目录 前言 A题 B题 C题 D题 E题 传送门 前言 没错因为蒟蒻太菜了这场的最后一道题也咕掉了,只有AAA至EEE的题解233 A题 传送门 题意简述:给出一棵带点权的树,根节点深度为111, ...

  4. Codeforces 381 简要题解

    做的太糟糕了...第一题看成两人都取最优策略,写了个n^2的dp,还好pre-test良心(感觉TC和CF的pretest还是很靠谱的),让我反复过不去,仔细看题原来是取两边最大的啊!!!前30分钟就 ...

  5. [bzoj\lydsy\大视野在线测评]题解(持续更新)

    目录: 一.DP 二.图论 1.最短路 2.强连通分量 三.利用单调性维护 四.贪心 五.数据结构 1.并查集 六.数学 1.计数问题 2.数学分析 七.博弈 八.搜索 /////////////// ...

  6. Codeforces 873 简要题解

    文章目录 A题 B题 C题 D题 E题 F题 传送门 A题 传送门 题意: 一个人要做nnn件事,时间花费分别为a1,a2,...,an,a1≤a2≤a3≤...≤ana_1,a_2,...,a_n, ...

  7. Codeforces 1120 简要题解

    文章目录 A题 B题 C题 D题 E题 F题 传送门 A题 传送门 题意简述:给你一个mmm个数的数列,现在规定把一个数列的1,2,...,k1,2,...,k1,2,...,k分成第一组,把k+1, ...

  8. Codeforces 1114 简要题解

    文章目录 A题 B题 C题 D题 E题 F题 传送门 然而这场div2div2div2没有什么难度比较大的题 A题 传送门 题意简述:三个人分别至少选x,y,zx,y,zx,y,z件物品,有三种物品数 ...

  9. Codeforces 1110 简要题解

    文章目录 A题 B题 C题 D题 E题 F题 G题 传送门 众所周知ldxoildxoildxoi这种菜鸡选手是不会写HHH题的,因此该篇博客只有AAA题至GGG题的题解,实在抱歉. A题 传送门 题 ...

随机推荐

  1. 微信小程序开发——导航失效的解决办法

    异常描述: 使用 navigator 导航,各种属性配置没问题,就是点击死活不跳转. 异常分析: 遇到这种情况,要先考虑的就是当前配置的导航url,是不是已经使用在tabBar中,因为小程序对于nav ...

  2. windows安装ssh工具opensssh

    本篇教程将告诉你如何在Windows 10设备上启用SSH,让您可以通过命令提示符连接到远程服务器 工具/原料   首先你需要下载windows版本的OpenSSH, 本教程以7.2p1-1版本为例 ...

  3. 导出可运行jar包

    @参考文档 选中项目右击export 可运行jar文件 Extract required libraries into generated JAR:将所需库导出到导出的jar包根目录下,效果如下 Pa ...

  4. 关于viewport我自己的理解

    其实即使不在html中添加meta viewport标签,每个移动端浏览器都会有一个默认的viewport,只是这个viewport的宽度是980,然后做1:3或者1:2的自动缩放.所以当不在html ...

  5. linux命令学习之:sort

    sort命令是在Linux里非常有用,它将文件进行排序,并将排序结果标准输出.sort命令既可以从特定的文件,也可以从stdin中获取输入. 语法 sort  (选项)  (参数) 选项 sort将文 ...

  6. Django TypeError: isinstance() arg 2 must be a type or tuple of types

    报错: TypeError: isinstance() arg must be a type or tuple of types from django.db import modelsfrom dj ...

  7. Oracle_高级功能(6) 分区

    oracle分区表1.分区表: 当表中的数据量不断增大,查询数据的速度就会变慢,应用程序的性能就会下降,这时就应该考虑对表进行分区. 表进行分区后,逻辑上表仍然是一张完整的表,只是将表中的数据在物理上 ...

  8. win10安装.net3.5

    近日有网友反映在windows10_64位系统电脑上安装Net framework3.5,操作时总失败,怎么办呢?小编下面就介绍win10 64位系统无法安装Net framework3.5的两种解决 ...

  9. linux设置系统时间和时区

    1.设置系统时间 date命令将日期设置为2014年6月18日 ----   date -s 06/18/14 将时间设置为14点20分50秒 ----   date -s 14:20:50 将时间设 ...

  10. [Robot Framework] 通过Robot Remote Server调用White Library测试WPF开发的桌面产品

    参考 : https://github.com/jatalahd/WhiteRobotLibrary 通过此源代码编译WhiteRobotLibrary.dll,然后把高亮标记的这5个dll全部拷贝到 ...