文章目录

传送门

又一场原地爆炸的比赛。

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. 倒计时问题java

    public static void main(String args[]){ Scanner sc = new Scanner(); int x = sc.nextInt(); System.out ...

  2. laravel excel导出调节列宽度,对某列中数据颜色处理

    //$cellData 表格标题栏各名称数组 //$result 表格内容数组//$items getForDataTable得到的表格数据 $result = array_merge($cellDa ...

  3. http://www.bugku.com:Bugku——变量1(http://120.24.86.145:8004/index1.php)

           之前立志做出需要编码解决和时间相关的那道CTF题目,但是这次没找到,相关人士找到了麻烦告诉我一声.本次再学习一下子关于正则表达式和PHP的相关知识.开课咯-.-   刚看题目就发现提示, ...

  4. 【zookeeper】使用场景

    以下场景是我认为的zookeeper可能会大显身手的场景. 场景1:配置新增和更新 我们可以将zookeeper部署成一个配置服务,实现配置的存储和发布等功能. 具体的原理是:zookeeper可以按 ...

  5. Delphi:MSBuild编译dproj工程

    Delphi之命令行编译工程,传统是用dcc32来编译的,它需要设置一大堆参数. 自Delphi 2007以后,支持MSBuild编译,它直接编译.dproj工程文件,所有编译需要的东西,都已在其中设 ...

  6. [leetcode]791. Custom Sort String自定义排序字符串

    S and T are strings composed of lowercase letters. In S, no letter occurs more than once. S was sort ...

  7. day 11 生成器

    生成器生成器本质就是迭代器,生成器是自己用python代码写的迭代器 将函数变成生成器yield用next 取值一个next,对应一个yield def func(): yield 111 yield ...

  8. 使用jquery刷新当前页面

    div的局部刷新 $(".dl").load(location.href+" .dl"); 全页面的刷新方法 window.location.reload()刷 ...

  9. nginx安装扩展 sub_filter&http_ssl_module

    nginx之所以轻,因为默认没有安装各种各样的扩展: nginx安装扩展插件: 下面列出两个可能会用到的插件 一.sub_filter内容过滤器,这个在nginx做http转发的时候会很常用 1.下载 ...

  10. 比特币学习-Transaction的locktime属性

    Locktime, also known as nLockTime from the variable name used in the reference client, defines the e ...