2019-2020 ICPC, NERC, Northern Eurasia Finals B,C,L,J,K

B:一定是奇数个颜色,且中间的颜色的个数+1就是答案。其他都是不可能的。

C:枚举那个人竞选成功即可

L:先处理1-K行。   一行一行进行处理,第一列直接从小到大,第二列往后,判断前一列与第k个字符串的那一列的字符相同的位置最上面在哪,然后从上往下填字典序小的字符。依次类推填好后再填剩下的就行。先填的是个倒三角

以上是签到题。。

J:枚举屏幕大小,屏幕大小一定小于等于最小的图标数+1.

再枚举图标种类,看看当前大小能否装下所有种类图标,可以的话就记录数量,取最小即可。

复杂度0(n),因为最小的图标数*图标种类一定小于等于n。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
//typedef __int128 LL;
//typedef unsigned long long ull;
//#define F first
//#define S second
typedef long double ld;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<ld,ld> pdd;
const ld PI=acos(-1);
const ld eps=1e-9;
//unordered_map<int,int>mp;
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
//#define a(i,j) a[(i)*(m+2)+(j)]  //m是矩阵的列数
//pop_back()
const int seed=131;
const int M = 2e6+7;
/*
int head[M],cnt;
void init(){cnt=0,memset(head,0,sizeof(head));}
struct EDGE{int to,nxt,val;}ee[M*2];
void add(int x,int y,int z){ee[++cnt].nxt=head[x],ee[cnt].to=y,ee[cnt].val=z,head[x]=cnt;}
*/
int mp[M];
int main()
{
	int t;
  	scanf("%d",&t);
	while(t--)
  	{
  		int n,x;
  		scanf("%d",&n);
  		for(int i=1;i<=n;i++)mp[i]=0;
  		vector<int>v;v.clear();
  		for(int i=1;i<=n;i++)
  			scanf("%d",&x),mp[x]++;
		int s=n+1;
		for(int i=1;i<=n;i++)
			if(mp[i])v.pb(mp[i]),s=min(s,mp[i]);
		//sort(v.begin(),v.end());
		int mi=n+1;
		for(int i=1;i<=s+1;i++)//屏幕的大小
		{
			int ans=0;
			for(auto x:v)//枚举所有种类,看看每个种类是否满足 
			{
				int z=x/i;
				int c=x%i;
				if(c+z>=i-1||c==0)//可以
				ans+=z+(c!=0);
				else  {
					ans=-1;
					break;
				}
			}
			if(ans>0)mi=min(mi,ans);
		//	cout<<i<<"  "<<ans<<endl;
		} 
		printf("%d\n",mi);
	}
	return 0;
}

K;

思路基本都在代码里了。

要明确:一个序列只能对应一个数,一个数也只能对应一个序列。(位置顺序固定的序列)

这一题就转化为了求满足条件的序列个数-1.

条件:

1.第i位的数要小于i+1。//第i位是一个数除以i+1的余数

2.最后一位不能为0,//商不可能为0

 

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
//typedef __int128 LL;
//typedef unsigned long long ull;
//#define F first
//#define S second
typedef long double ld;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef pair<ld,ld> pdd;
const ld PI=acos(-1);
const ld eps=1e-9;
//unordered_map<int,int>mp;
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
//#define a(i,j) a[(i)*(m+2)+(j)]  //m是矩阵的列数
//pop_back()
const int seed=131;
const int M = 2e6+7;
/*
int head[M],cnt;
void init(){cnt=0,memset(head,0,sizeof(head));}
struct EDGE{int to,nxt,val;}ee[M*2];
void add(int x,int y,int z){ee[++cnt].nxt=head[x],ee[cnt].to=y,ee[cnt].val=z,head[x]=cnt;}
*/
int s[50],sz;
ll cal()
{
	//如果s序列固定对应的数只有一个
	//同时数固定对应的s序列也只有一个
//我们现在计算满足条件的序列有几个就是计算数有几个
//条件:设第i位是第i次操作的结果,则s[i]<i.且最后一位不能为0,
//我们先按最后一位可以为0算,再去掉一个0算一遍,减掉即可 
	ll ans=1;
	for(int i=1;i<=sz;i++)//第i位要小于i+1(第i位是除以i+1的余数) 
	{
		ll tp=0;
		for(int j=1;j<=sz;j++)if(s[j]<i+1)tp++;
		ans*=(tp-i+1);//第i位有tp个数放的可能,但前面i-1位已经用掉了i-1(前面的数的范围一定在后面数的范围之内) 
	}
	//现在开始去掉重复数的重复计算。比如1 1 1 2,1 1 2 1, 1 2 1 1三种,但是我们算到18种,多了3!种。每个数的重复都要去掉 
	int f=0;
	for(int i=1;i<=sz;i++)
	{
		if(s[i]==s[i-1])f++;
		else f=1;
		ans/=f;
	 } 
	 return ans;
}
int main()
{
	int t;
  	scanf("%d",&t);
	while(t--)
  	{
  		ll n;
  		scanf("%lld",&n);
  		int tp=2;sz=0;
		memset(s,0,sizeof(s));
		while(n)
  		{
  			s[++sz]=n%tp;
  			n/=tp++;
		}
	//	for(int i=1;i<=sz;i++)
	//		printf("%d ",s[i]);
	//	puts("");
		sort(s+1,s+1+sz);
		ll ans=cal();
	//	printf("--       %lld\n",ans);
		if(s[1]==0)
		{
			for(int i=1;i<=sz;i++)s[i]=s[i+1];
			sz--;
			ans-=cal();//末尾不能放0,减去这个影响 
		}
		printf("%lld\n",ans-1);
	}
	return 0;
}

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值