Codeforces Round #708 (Div. 2)


A、Meximization

题目大意:MEX[ i ]代表数组前 i 个数中没有出现的最小非负数,给一个数组,重新排列使他MEX的和最小。
解题思路:对于所有出现的数字从小到大(可以尽快提高MEX的值),再输出重复的数。
AC代码

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <cstring>
#include <vector>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <climits> 
#include <cmath> 
#include <set>
typedef long long ll;
const int maxn=1e2 + 5;
const int INF=0x3f3f3f3f;
using namespace std;
int t,q,n,cnt[maxn];
int main()
{
	cin>>t;
	while(t--){
		cin>>n;
		memset(cnt,0,sizeof(cnt));
		for(int a=0;a<n;a++)
		{
			cin>>q;
//			cout<<q<<endl;
			cnt[q]++;
		}
//		cout<<cnt[4]<<endl;
		for(int a=0;a<=100;a++){
			if(cnt[a]>0)
			{
				cout<<a<<" ";
				cnt[a]--;
			}
		}
		for(int a=0;a<=100;a++){
			while(cnt[a]>0)
			{
				cout<<a<<" ";
				cnt[a]--;
			}
		}
		cout<<endl;
	}
	return 0; 
}

B、M-arrays

题目大意:多组输入,对于每组给出 n 个数和 m 把n个数分成多个序列使每个序列的相邻元素和都是m的倍数,或者只有一个元素。
解题思路:对于输入的数,不管他的值是多少对于我们有用的是他模m的余数是多少,只要连个数的模m余数的和是m那他们的和就可以被m整除,所以首先使 a[ i ] %=m,由于m<=1e5 ,即 a[ i ] %m <= 1e5 所以可以开个数组来存每个余数的出现次数。
之后是配对,余数m-x 和 x 配对,多余的数没有办法和其他数配对所以只能单独一个序列。要注意的数x-m 和 x配对可以是 ababa 即有一个数的出现此时可以必另一个多一次。
还有一种情况是当m为偶数时,m/2只能和自己配对,所以只要这个数出现了就可以单独用一个序列。
AC代码

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <cstring>
#include <vector>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <climits> 
#include <cmath> 
#include <set>
typedef long long ll;
const int maxn=1e5 + 5;
const int INF=0x3f3f3f3f;
using namespace std;
int n,m,t,q;
int arr[maxn];
int main()
{
	cin>>t;
	while(t--)
	{
//		cout<<(666%1)<<endl;
		memset(arr,0,sizeof(arr));
		cin>>n>>m;
		for(int a=0;a<n;a++)
		{
			cin>>q;
			q%=m;
			arr[q]++;
		}
//		cout<<arr[0]<<endl;
		int ans=0;
		if(arr[0])ans++;
		int tmp=0;
		for(int a=1;a<m/2;a++)
		{
			if(arr[a]||arr[m-a])
			{
//				cout<<"add "<<a<<endl;
				tmp = abs(arr[a]-arr[m-a]);
				if(tmp)tmp--;
				ans+=(tmp+1);
				
			}
		}
		if(m%2==0)
		{
			if(arr[m/2])
				ans++;
		}else
		{
			if(arr[m/2]+arr[m/2+1] && m!=1)
			{
				tmp = abs(arr[m/2]-arr[m/2+1]);
				if(tmp)tmp--;
				ans+=(tmp+1);
//				cout<<"add 1222"<<endl;
			}
		}
		cout<<ans<<endl;
		
	}
	return 0; 
}

C1、 k-LCM (easy version)

题目大意:多组输入给出n和k(k始终为3)求k个数,使其和为 n 最小公倍数不大于 n/2 。
解题思路:如果 n%4=0那么直接输 n/2 n/4 n/4最大公倍数是n/2
如果 n%2=0 && n%4!=0 输出 2 n/2-1 n/2-1 最大公倍数是 n/2-1
如果 n数奇数 那么直接输 1 n/2 n/2 最大公倍数是n/2
AC代码

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <cstring>
#include <vector>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <climits> 
#include <cmath> 
#include <set>
typedef long long ll;
const int maxn=1e3 + 5;
const int INF=0x3f3f3f3f;
using namespace std;
int n,k,t;
int main()
{
	cin>>t;
	while(t--)
	{
		cin>>n>>k;
		int ans=0;
		if(n%2==0 && n/2%2==0)
		{
			cout<<n/2/2 <<" "<<n/2/2 <<" "<<n/2<<endl;
		}
		else if(n%2==0 && n/2%2==1)
		{
			cout<<2<<" "<< n/2-1 <<" " << n/2-1<<endl;
		}else 
		{
			cout<<1<<" "<<(n-1)/2<<" "<<(n-1)/2<<endl;
		}
	}
	return 0; 
}

C2、 k-LCM (hard version)

题目大意:题目和c1是一样的区别是这里k不一定是3
解题思路:输出k个1 就可以把问题转化为 c1 此时n为n-(k-3) ,k为3
AC代码

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <cstring>
#include <vector>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <climits> 
#include <cmath> 
#include <set>
typedef long long ll;
const int maxn=1e3 + 5;
const int INF=0x3f3f3f3f;
using namespace std;
int n,k,t;
int main()
{
	cin>>t;
	while(t--)
	{
		cin>>n>>k;
		int ans=0;
		n-=(k-3);
		if(n%2==0 && n/2%2==0)
		{
			cout<<n/2/2 <<" "<<n/2/2 <<" "<<n/2;
		}
		else if(n%2==0 && n/2%2==1)
		{
			cout<<2<<" "<< n/2-1 <<" " << n/2-1;
		}else 
		{
			cout<<1<<" "<<(n-1)/2<<" "<<(n-1)/2;
		}
		for(int a=0;a<k-3;a++)
		{
			cout<<" "<<1;
		}
		cout<<endl;
	}
	return 0; 
}

D、Genius

待补

E1、 Square-free division (easy version)

题目大意:给一个数组,最少可以把它划分成多少段,使每一段中的任意两个数的积不是完全平方数。
解题思路:对于每一个数把它因子中的完全平方数数除掉,那么剩下的就是单个素数的积。和他不能在一个片段的数就是等于它的数。标记每一个数的下一个不能共存的数的位置之后从头开始遍历,将其划分
AC代码

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <cstring>
#include <vector>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <climits> 
#include <cmath> 
#include <set>
typedef long long ll;
const int maxn=2e5 + 5;
const int maxp = 1e4;
const int INF=0x3f3f3f3f;
using namespace std;
int n,k,t,arr[maxn];
bool vis[maxn];
map<int,bool> ou;
bool isq(int i)
{
	int q = sqrt(i);
	return q*q==i;
}
ll p[maxp],pcnt;
int num[maxp];
void getP()
{
	pcnt=0;
	memset(num,1,sizeof(num));
	for(int a=2;a<=maxp;a++)
	{
		if(num[a])p[pcnt++] = a;
		for(int b=0;b<pcnt;b++)
		{
			if(a*p[b]>maxp)break;
			num[a*p[b]] = false;
			if(a%p[b]==0)break;
		}
	}
}
int main()
{
	getP();
	for(int a=0;a<pcnt;a++)
	{
		p[a]*=p[a];
	}
	cin>>t;
	while(t--)
	{
		ou.clear();
		cin>>n>>k;
		int ans=0;
		for(int a=0;a<n;a++)
		{
			cin>>arr[a];
			for(int b=0;b<pcnt && arr[a]>=p[b];b++)
			{
				if(arr[a]%p[b]==0)arr[a]/=p[b];
			}
		}
		for(int a=0;a<n;a++)
		{
			if(ou[arr[a]])
			{
				ans++;
				ou.clear();
			}
			ou[arr[a]]=1;
		}
		
		cout<<ans+1<<endl;
	}
	return 0; 
}

E2、Square-free division (hard version)

待补题

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值