文章目录

传送门

又一场原地爆炸的比赛。

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. Mac idea error=13, Permission denied

    问题 12:26 Error running 'rs8080': Cannot run program "/Users/xxx/software/apache-tomcat-8.5.37/b ...

  2. c# 键值对的方式post提交

    DataContractJsonSerializer jsQcData = new DataContractJsonSerializer(typeof(DATA<data>));//DAT ...

  3. 客户端无法重新使用 SPID 为 63 的会话,该会话已被重置用于连接

    客户端无法重新使用 SPID 为 %d 的会话,该会话已被重置用于连接池.失败 ID 为 %d. 此错误可能是由于先前的操作失败引起的.请查看错误日志,找出在显示此错误消息之前刚发生的失败操作. 20 ...

  4. swift - VFL - 1.循环创建控件 2.metrics使用

    1. /// 创建单个热门项目itemView private func creatProcduceItemView(producrName: String , producePrice: Strin ...

  5. Redis 与Spring-data-redis 整合后封装的工具类

    此工具类方法是使用了redis 与spring 整合后,才可以使用的工具类,将 spring-data-redis 一些我们开发中常用的方法进行了封装,方便我们日常开发中进行调用: package c ...

  6. Java11-java基础语法(十)类设计综合案例

    Java11-java语法基础(十)类设计综合案例 一.类综合设计方法 1.类设计步骤 (1)分析数据成员 (2)分析成员方法和构造方法 (3)画出类图 (4)编码测试 2.具体问题 1)分析数据成员 ...

  7. idea spring-boot gradle mybatis 搭建开发环境

    使用工具idea 2017.2开发,gradle构建项目,使用的技术有spring-boot.mybatis 1.新建项目 说明:1.src为源码路径,开发主要在src下 2.src/main/jav ...

  8. js 逻辑运算符

    两个逻辑运算符的操作顺序在自己的脑海里一直理不清,用js做了个实验 <script type="text/javascript">    if(false && ...

  9. 哪些intel 网卡支持SR-IOV

    哪些英特尔®以太网适配器和控制器支持 SR-IOV? 英特尔®以太网融合网络适配器 X710 系列 英特尔®以太网聚合网络适配器 X710-da2 英特尔®以太网聚合网络适配器 X710-da4 英特 ...

  10. 如何让一个Java新手快速入门?

    问题中问到如何让java新生快速入门,既然想快速入门的话那最简单粗暴的方法就是多看视频,加上跟着视频敲代码,刚开始可能不知道是什么意思,敲得多了就慢慢知道是什么意思了. 刚开始建议在网上找那种结合自己 ...