某5道CF水题

1.PolandBall and Hypothesis

题面在这里!

大意就是让你找一个m使得n*m+1是一个合数。

首先对于1和2可以特判,是1输出3,是2输出4。

然后对于其他所有的n,我们都可以非常快的找到一个最小的与它互质的质数p(考虑反证法),并且满足p<n。

这样就相当与解一个同余方程 n*m = p-1 (mod p) , 解出的m可以保证 n*m+1 是 p 的倍数,也就是合数了。

又因为gcd(p,n)==1,所以这个方程肯定有解,直接求一个 n 在mod p意义下的逆元然后乘上 p-1 就行了。

这个方法牛逼的地方就在它的复杂度(如果不算快速幂和n大了要用高精度的话)是比log还小的,所以n甚至可以出到 2^63 级别。

(但这样就不好写checker了吧2333)

#include<bits/stdc++.h>
#define ll long long
using namespace std;

int zs[10]={2,3,5,7,11,13,17,19,23,29},n,i;

inline int ksm(int x,int y,const int ha){
	int an=1;
	for(;y;y>>=1,x=x*(ll)x%ha) if(y&1) an=an*(ll)x%ha;
	return an;
}

int main(){
	scanf("%d",&n);
	if(n==1) puts("3");
	else if(n==2) puts("4");
	else for(;i<10;i++) if(n%zs[i]){
		const int ha=zs[i];
		printf("%d\n",(ha-1)*(ll)ksm(n%ha,ha-2,ha)%ha);
		break;
	}
	return 0;
}

2.PolandBall and Game

题面在这里!

很裸很裸的一个贪心,肯定是优先选重叠的,所以hash一下直接贪就好啦QWQ

#include<bits/stdc++.h>
#define ll unsigned long long
using namespace std;

unordered_map<ll,int> mmp;
int n,m,tot;
ll now;
char c;

int main(){
	scanf("%d%d",&n,&m);

	for(int i=1;i<=n;i++){
		for(c=getchar(),now=0;c!=‘\n‘;c=getchar()) now=now*(ll)73+c-‘a‘+3ll;
		if(!now){ i--; continue;}
		mmp[now]=1;
	}
	for(int i=1;i<=m;i++){
		for(c=getchar(),now=0;c!=‘\n‘;c=getchar()) now=now*(ll)73+c-‘a‘+3ll;
		if(!now){ i--; continue;}
		if(mmp[now]) tot++;
	}	

	n+=(tot&1);
	puts(n>m?"YES":"NO");

	return 0;
}

3.PolandBall and Forest

题面在这里!

又是一道神仙题。

可以证明同一颗树里面的p[]一定是点标号严格最小的直径中的一个端点,这个玩意还是画画图比较好理解。。。

于是我们就找一找这种端点互相对应的直径数就好啦。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=10005;

int n,a[N],cnt;

int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",a+i);
	for(int i=1;i<=n;i++) if(a[i]>=i&&a[a[i]]==i) cnt++;
	printf("%d\n",cnt);
	return 0;
}

4.PolandBall and Gifts

题面在这里!

把置换拆成环之后,可以发现一个位置不带礼物会影响环上它和它的后继,那么两种极值肯定是希望 影响尽量重叠 或者 尽量不重叠。

最小化的话就是尽量重叠,可以发现当且仅当物品看成是环大小的背包可以凑出k的时候答案是k;否则就是k+1。

直接背包肯定会凉凉啊,但是多重背包可以把每个物品的体积拆成 1 + 2 + 4 + ... + lef,偶数项都可以放到更大的体积的物品中去(因为 ∑每种物品的体积×个数 = N,所以不会出事),所以每种物品最多加两次,并且最多加sqrt(N)种不同的物品(想一想为什么),于是bitset一下复杂度刚刚好是 3*1e7,卡着过(虽然实际复杂度非常优秀)。

最大化非常简单,直接贪心就好啦QWQ

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e6+5;

inline int read(){
	int x=0; char ch=getchar();
	for(;!isdigit(ch);ch=getchar());
	for(;isdigit(ch);ch=getchar()) x=x*10+ch-‘0‘;
	return x;
}

bitset<N> B;
int n,p[N],k,K,ans[2],lef,c[N];
bool v[N];

inline int getlen(int x){
	int an=0;
	for(;!v[x];x=p[x]) v[x]=1,an++;
	return an;
}

inline void solve0(){
	for(int i=1,now;i<=n;i++) if(!v[i]){
		now=getlen(i),c[now]++;
		lef+=now&1,now^=now&1;
		if(K>=(now>>1)) K-=now>>1,ans[0]+=now;
		else if(K) ans[0]+=K<<1,K=0;
	}
	if(K) ans[0]+=min(K,lef);
}

inline void solve1(){
	B[0]=1;
	for(int i=1;i<=n;i++) if(c[i]){
		B|=B<<i,c[i]--;
		if(c[i]&1) B|=B<<i;
		c[i<<1]+=c[i]>>1;
	}
	ans[1]=B[k]?k:k+1;
}

int main(){
    n=read(),K=k=read();
    for(int i=1;i<=n;i++) p[i]=read();
    solve0(),solve1();
    printf("%d %d\n",ans[1],ans[0]);
    return 0;
}

5.Fix a Tree

题面在这里!

首先原图肯定是若干基环树,我们的任务就是最后只留一个联通的基环树,并且环还得是自环。

先看一看原图中有没有自环,如果有的话就随便找一个当根。

然后用并查集维护联通性,如果i和p[i]已经在一个联通分量里的话,就把p[i]指向根,并且ans++。

当然,如果原来就没有根的话那么就把i设为根,最后答案是一样的。

可以证明答案总是 : 联通分量个数 - [原图中有没有自环]

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=200005;

inline int read(){
	int x=0; char ch=getchar();
	for(;!isdigit(ch);ch=getchar());
	for(;isdigit(ch);ch=getchar()) x=x*10+ch-‘0‘;
	return x;
}

void W(int x){ if(x>=10) W(x/10); putchar(x%10+‘0‘);}

int p[N],n,root,a[N],ans;

int getf(int x){ return p[x]==x?x:(p[x]=getf(p[x]));}

int main(){
	n=read();
	for(int i=1;i<=n;i++) p[i]=i,a[i]=read();
	for(int i=1;i<=n;i++) if(a[i]==i){ root=i; break;}

	for(int i=1,fa,fb;i<=n;i++) if(i!=root){
		fa=getf(i),fb=getf(a[i]);
		if(fa!=fb) p[fa]=fb;
		else{
			ans++;
			if(root) a[i]=root;
			else root=a[i]=i;
		}
	}

	W(ans),puts("");
	for(int i=1;i<=n;i++) W(a[i]),putchar(‘ ‘);
	return 0;
}

原文地址:https://www.cnblogs.com/JYYHH/p/9293511.html

时间: 2024-10-14 15:34:16

某5道CF水题的相关文章

几道cf水题

题意:给你包含n个元素的数组和k种元素,要求k种元素要用完,并且每种颜色至少用一次,n个元素,如果某几个元素的值相同,这些个元素也不能染成同一种元素. 思路:如果元素个数n小于k或者值相同的元素的个数大于k,那么一定无解,输出-1.用一个num[a[i]]记录每种相同值的元素出现次数,若大于k,无解.这道题的关键在于如何处理值相同的这些元素,可以用一个二维数组f[i][j]来表示状态,其中i表示对应元素值,j代表颜色.只要对于相同的i,j值不同就可以了.每个元素用什么颜色记录在一个数组ans[i

一道cf水题再加两道紫薯题的感悟

1. 遇到一个很大的数除以另一个数时,可以尝试把这个很大的数进行,素数因子分解. 2. 遇到多个数的乘积与另一个数的除法时,求是否能整除,可以先求每一个数与分母的最大公约数,最后若分母数字为1,则证明可整除.或者把分子上的每个数进行素数因子分解,分母上的数也进行素数因子分解,若分子上的与分母上相同素数因子进行比较,分子上的素数因子指数大于分母位置上的,则证明可整除. 3. 遇到乘法的时候注意越界问题. 4. 遇到求某一个区间内,满足某一特征的数的个数,而这个特征与因子,约数有关,尝试用埃筛的方法

CODEVS1163访问艺术馆(第一道大师水题)

题目描述 Description 皮尔是一个出了名的盗画者,他经过数月的精心准备,打算到艺术馆盗画.艺术馆的结构,每条走廊要么分叉为二条走廊,要么通向一个展览室.皮尔知道每个展室里藏画的数量,并且他精确地测量了通过每条走廊的时间,由于经验老道,他拿下一副画需要5秒的时间.你的任务是设计一个程序,计算在警察赶来之前(警察到达时皮尔回到了入口也算),他最多能偷到多少幅画. 输入描述 Input Description 第1行是警察赶到得时间,以s为单位.第2行描述了艺术馆得结构,是一串非负整数,成对

一道cf水题

题意:输入数字n表示字符串中元素个数,字符串中只含有RGB三个字符,现在要求任意两个相同的字符他们的下标之差能整除3. 思路:任意两个相同的字符的下标能整除3,也就是任意三个为一组的字符串当中的字符不能相同,那么只要某一组字符确定了,那么字符串中所有字符也就确定了,我们不妨来枚举前三个字符可能的排列,只要第一组确定了,后面也就全部确定了(当时自己去字符串里面找第一个不重复的三个字符组不就是这个意思么).接下来第一组确定后,由于后面所有的字符都和它相同,所以我们只需要遍历一遍统计后面与他不对应的字

在cf水题の记录

CF1158C 题意:有排列p, 令\(nxt_i\)为\(p_i\)右侧第一个大于\(p_i\)的数的位置,若不存在则\(nxt_i=n+1\) 现在整个p和nxt的一部分丢失了,请根据剩余的nxt,构造出一个符合情况的p,输出任意一解. 使有解的充要条件是对于每一个i不存在\(j\in(i,nex_i)\)满足\(nex_j>nex_i\) 也就是说对于每个\(i\)向\(nxt_i\)连一条边,然后没有两条边相交 对于点\(i\)向\(nex_i\)和满足\(j<i \ \wedge n

刷了500道水题是什么体验?

并没有什么卵用. 我马上大二了,大一两学期目测切了1000道水题了,毫无意义. 至今不理解kmp和后缀数组,只会模板.数论和博弈论是什么?能吃吗?只会打表.图论至今不会tarjan,话说dlx是什么?插头dp,这是什么?数据结构还好,经常做高中生的题,可持久化可持久化线段树也能花一下午时间写出来,然而并不会考. 平时做题只刷水题,遇到难题的时候,随手搜题解,看了看,哇,这居然能这么搞!然后抄一遍别人代码,交上去ac. cf一年几乎没缺过,花了大一上半年时间才滚上div1.然而至今紫号一堆,黄名一

大数--几道水题,用来学学JAVA

几道水题,练习一下JAVA写大数 poj2305  Basic remains 大数可以直接用非十进制读入,读入的数在变量中是十进制的 输出的时候要先用BigInteger的toString方法转换为相应的进制 1 import java.math.*; 2 import java.util.*; 3 class Main 4 { 5 public static void main(String[] args) 6 { 7 Scanner cin = new Scanner(System.in)

POJ百道水题列表

以下是poj百道水题,新手可以考虑从这里刷起 搜索1002 Fire Net1004 Anagrams by Stack1005 Jugs1008 Gnome Tetravex1091 Knight Moves1101 Gamblers1204 Additive equations 1221 Risk1230 Legendary Pokemon1249 Pushing Boxes 1364 Machine Schedule1368 BOAT1406 Jungle Roads1411 Annive

CF 628A --- Tennis Tournament --- 水题

CF 628A 题目大意:给定n,b,p,其中n为进行比赛的人数,b为每场进行比赛的每一位运动员需要的水的数量, p为整个赛程提供给每位运动员的毛巾数量, 每次在剩余的n人数中,挑选2^k=m(m <=n)个人进行比赛,剩余的n-m个人直接晋级, 直至只剩一人为止,问总共需要的水的数量和毛巾的数量 解题思路:毛巾数很简单: n*p即可 水的数量:1,2,4,8,16,32,64,128,256,512,提前打成一个表, 根据当前剩余的人数n在表中二分查找最大的小于等于n的数,结果即为本次进行比赛