文章目录

传送门

又一场原地爆炸的比赛。

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. 14. Longest Common Prefix (截取字符串)

    Write a function to find the longest common prefix string amongst an array of strings. char* longest ...

  2. JMeter 连接MySQL

     第一步:添加JDBC 驱动 第二步:在线程组 下面添加一个“JDBC Connection Configuration” 第三步:在“线程组”,在下面添加一个“JDBC request”

  3. Netty实践一(数据通信)

    我们需要了解下在真正项目应用中如何去考虑Netty的使用,大体上对于一些参数设置都是根据服务器性能决定的.这个不是最主要的. 我们需要考虑的问题是两台机器(甚至多台)使用Netty的怎样进行通信,大体 ...

  4. TZOJ 3663 最长路径(floyd)

    描述 网络是由很多交换机与网线组成的,网络中的信息可能会在这些网络中不断转发,给定任意两个交换机,我们需要从中找到最快的路径进行转发,我们定义转发过程中所经过的网线条数为两个交换机之间的路径长度.如果 ...

  5. 民生银行十五年的数据体系建设,深入解读阿拉丁大数据生态圈、人人BI 是如何养成的?【转】

    早在今年的上半年我应邀参加了由 Smartbi 主办的一个小型数据分析交流活动,在活动现场第一次了解到了民生银行的阿拉丁项目.由于时间关系,嘉宾现场分享的内容非常有限.凭着多年对行业研究和对解决方案的 ...

  6. java调用dll

    @参考文章1,@参考文章2 根据上篇博客(参考文章2)java生成的dll测试 1,新建java项目,新建WebContent,子目录建WEB-INF\lib,加进jna-3.4.0.jar 新建ja ...

  7. swift - 本地通知2 - 啰嗦版

    1. import UIKit @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { var windo ...

  8. dup

    dup是一个操作符,由编译器识别处理,和db.dw.dd等数据定义伪指令配合使用,用来进行数据的重复. 例如 db  3  dup (0) 定义了3个字节,它们的值都是0,相当于db 0,0,0 db ...

  9. @params、@PathVariabl和@RequestParam用法与区别

    [1]params params: 指定request中必须包含某些参数值是,才让该方法处理. @RequestMapping(value = "testParamsAndHeaders&q ...

  10. YII2中behavior行为的理解与使用

    YII2中的行为说白了就是对组件功能的扩展,在不改变继承关系的条件下. 行为附加到组件后,行为将注入自已的方法和属性到组件,可以像组件访问自定义的方法和属性一样访问行为. 注意行为是对功能的扩展,不要 ...