Codeforces Round #561 (Div. 2) ABCDE

传送门

A.Silent Classroom

水题。

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    map<char,int>mp;
    int main()
    {
    	int n;
    	cin>>n;
    	for(int i=1;i<=n;i++)
    	{
    		string s;
    		cin>>s;
    		mp[s[0]]++;
    	}
    	ll ans=0;
    	for(char i='a';i<='z';i++)
    	{
    		if(mp[i]>1)
    		{
    			if(mp[i]%2)
    			{
    //				cout<<mp[i]<<" "<<i<<endl;
    				int t=mp[i]/2;
    				for(int j=1;j<t;j++)
    				{
    					ans+=j;
    				}
    				for(int j=1;j<=t;j++)
    				{
    					ans+=j;
    				}
    			}
    			else
    			{
    //				cout<<mp[i]<<" "<<i<<endl;
    				int t=mp[i]/2;
    				
    				for(int j=1;j<t;j++)
    				{
    					ans+=j;
    				}
    				for(int j=1;j<t;j++)
    				{
    					ans+=j;
    				}
    			}
    		}
    	}
    	cout<<ans<<endl;
    	return 0;
    }

B. All the Vowels Please

满足行列都大于5就行了,后面乱构造一下就好了。

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    string s[10];
    int main()
    {
    	int k;
    	cin>>k;
    	s[1]="aeiou";
     	s[2]="uaeio";
    	s[3]="ouaei";
    	s[4]="iouae";
    	s[5]="eioua";
    	s[6]="aaaaa";
    	
    	if(k<25)
    	{
    		cout<<-1<<endl;
    	}
    	else
    	{
    		int x=0,y=0;
    		for(int i=5;i<=200;i++)
    		{
    			for(int j=5;j<=200;j++)
    			{
    				if(i*j==k)
    				{
    					x=i,y=j;
    					break;
    				}
    			}
    			if(x+y!=0)
    			{
    				break;
    			}
    		}
    		if(x+y==0)
    		{
    			cout<<-1<<endl;
    			return 0;
    		}
    		for(int i=1;i<=x;i++)
    		{
    			if(i<=5)
    			{
    				cout<<s[i];
    			}
    			else
    			{
    				cout<<s[1];
    			}
    			for(int j=6;j<=y;j++)
    			{
    				cout<<s[1][i%5];
    			}
    		}
    	}
    	cout<<endl;
    	return 0;
    }

 C. A Tale of Two Lands

 对于|x|,|y|来说,x,y的正负并不会产生什么影响;对于|x−y|,|x+y|来说,x,y的正负也不会产生什么影响。所以我们就可以直接对ai取绝对值,只看为正数的情况就好了。只需要关注x-y的值是否大于当前值就行 然后尺取法就可以搞定 然后注意因为可能书太大 所以需要用long long

#include<cstdio>
#include<cmath>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<map>
#include<vector>
#define ll long long
using namespace std;
ll a[200010];
ll sum[200010];
int main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
		if(a[i]<0)
		{
			a[i]=-a[i];
		}
	}
	sort(a+1,a+n+1);
	/*for(int i=1;i<n;i++)
	{
		sum[i]=a[i+1]-a[i];
		sum[i]+=sum[i-1];
	}*/
	int l=1,r=2;
	ll sum=0;
	while(r<=n)
	{
		if(a[r]-a[l]<=a[l])
		{
			sum+=(r-l);
			r++;
		}
		else
		{
			l++;
		}
	}
	cout<<sum<<endl;
	return 0;
}

D

题意:给一个序列的首项与末项a,b,现在要求我们怎么可以使得这个序列中的每个数\large x_{i}=x_{i-1}+x_{i-2}+x_{i-3}+...+x_{1}+r_{i},(x>=2),其中1≤ri≤m。如果可行的话,请输出一种解。

思路:

因为每个r最少为1,所以我们先令所有的r=1,得到一个序列:a, a+1, 2∗a+2, 4∗a+4,...

我们发现i>=3,i>=3时,第i项是i+1项的二倍。所以这个序列增长很快!

​ 我们求只取这个序列中小于等于b的部分,那么我们得到一个序列A,长度为k (A为构造的序列)。

​ 我们令rem=b−A[k], 那么rem就是我们需要往这个序列中增加某些位置的r值,让rem减少到0,从而让A[k]等于b

​ 我们假设第i位的r增加1,那数组A中第i+1位的值增加1,第i+2位的值增加2第i+3位的值增加4,向后的第q位的值增加\large 2^{q-1},那么我们可以算出来对数组A第k位的值增加多少。换句话说对rem减少的贡献是多少。

​ 所以我们可以贪心的从第2位一直到第k位,假设此时考虑第i位, r增加1对rem的贡献减少val,那么我们就让第 i 位的 r增加y=min(m−1,rem/val).

​ 注意,当i=k的时候,对第rem减少的贡献也是1。

​ 如果最后rem为0,那么咱们构造的数组A就是解。

​ 否则一定无解。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll arr[1010];
ll r[1010];
ll rem;
ll check(ll ans,ll t)
{
	if(t==1)
	return ans+1;
	else
	return 2ll*ans;
}
ll getval(ll t)//算出来第i位增加1,对rem的贡献是多少
{
	if(t<=2)
	return 1;
	t-=2;
	return (1ll<<t);
}
bool solve(ll ta,ll m)
{
	for(int i=2;i<=ta;i++)
	{
		ll val=getval(ta-i+1);
		ll tot=min(m-1,rem/val);
		rem-=tot*val;
		r[i]+=tot;
	}
	if(rem!=0)
	return 0;
	ll sum=arr[1];
	for(int i=2;i<=ta;i++)
	{
		arr[i]=sum+r[i];
		sum+=arr[i];
	}
	return 1;
}
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		ll a,b,m;
		cin>>a>>b>>m;
		ll tot=0;
		arr[++tot]=a;
		while(check(arr[tot],tot)<=b)//处理得到初始的A数组
		{
			arr[tot+1]=check(arr[tot],tot);
			tot++;
		}
		for(ll i=2;i<=tot;i++)
		r[i]=1ll;
		rem=b-arr[tot];
		
		if(!solve(tot,m))//处理rem
		{
			cout<<-1<<endl;
			continue;
		}
		cout<<tot;
		for(int i=1;i<=tot;i++)
		cout<<" "<<arr[i];
		cout<<endl;
	}
	return 0;
}

E

题解

#include<bits/stdc++.h>
using namespace std;
int vis[55][10100];
int main()
{
	int m,n;
	cin>>m>>n;
	for(int i=1;i<=m;i++)
	{
		int t;
		cin>>t;
		for(int j=0;j<t;j++)
		{
			int x;
			cin>>x;
			vis[i][x]=1;
		}
	}
	for(int i=1;i<=m;i++)
	{
		for(int j=1;j<=m;j++)
		{
			if(i==j)
			continue;
			int flag=0;
			for(int k=1;k<=n;k++)
			if(vis[i][k]&&vis[j][k])
			{
				flag=1;
			}
			if(flag==0){
				cout<<"impossible"<<endl;
				return 0; 
			}
		}
	}
	cout<<"possible"<<endl;
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值