CF531 div3

                                                     http://codeforces.com/contest/1102                   

A:

输入一个n 将1--n  n个整数分成两个组合a,b,求sum(a)与sum(b)差绝对值的最小值

思路

找规律:

n=3  0  getsum(3)=6

n=4  0  getsum(4)=10

n=5  1  getsum(5)=15

所以 当sum(n)为奇数时 输出1 为偶数时输出0

#include 

using namespace std;
int getsum(int x)
{
    if(x%2==0)
        return x/2*(x+1);
    else
        return (x+1)/2*x;
}
int main()
{
    int n;
    cin>>n;
    if(getsum(n)%2==0)
        cout<<0<

B:

n个数,k种颜料,给n个数染色

要求:

1:每种颜料都要用到

2:每个数都要被染色

3:相同的数不能用相同的燃料

如果没有符合要求的染色方案,输出NO

若有,输出一种方案

思路:

用a,b数组记录输入数组,a记录输入顺序,最后输出时也是按照输入顺序,将b排序,保证相同数字分配到不同的颜色。

每种数字开一个相应的vector容器,存放分配到的颜色。最后按照a数组记录的输入顺序输出。

#include 
#include 
#include 
#include 
#define maxn 5005
using namespace std;

int main()
{
    int n,k;
    int a[maxn],b[maxn],vis[maxn];   //vis数组用来记录每种相同数字的个数
    memset(vis,0,sizeof(vis));
    vector  v[maxn];
    cin>>n>>k;
    for(int i=1; i<=n; i++)
    {
        cin>>a[i];
        vis[a[i]]++;
        b[i]=a[i];
    }
    for(int i=5000; i>=1; i--)
        if(vis[i]>k)                 //如果某相同数字的个数大于k 直接输出NO
        {
            cout<<"NO"<::iterator it;        //申请迭代器,用来输出
    cout<<"YES"<

C:

有n个门,伤害值为x,修复值为y,第二行n个数表示每扇门的生命值,两个人都以最好的策略轮流进行损坏,修复,回合数无限,门的生命值为0或小于0时门就不能再被修复。输出可以损坏多少门。

思路:

两种情况:

1.x>y:n扇门全部被损坏

2.x<=y:找到所有生命值小于等于x的门的个数k,则答案为(k+1)/2 可以理解为,一个人在一边损坏,另一个人在另一边修复,两人碰面时则不会再有门被损坏。

#include 
#define maxn 101
using namespace std;

int main()
{
    int n,x,y;
    int a[maxn];
    int sum=0;
    cin>>n>>x>>y;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        if(a[i]<=x)
            sum++;
    }
    if(x>y)
    {
        cout<

D:

输入一个n,接下来输入n个数 (0,1,2),每次调整一个数字,用最少的转换次数,使调整后的序列中三个数字的个数相等,且字典序最小。

思路:

a数组用来记录0,1,2分别出现了多少次,b数组用来记录0,1,2的个数与平均值的差,temp数组用来记录多出来的0,1,2,(按字典序),tot为多的字符的个数,now表示当前已更换的字符的个数,遍历字符串,每遍历一个字符,其a数组所记录的值减一,当满足条件时,更换字符。

#include 
#include 
#define maxn 300005
using namespace std;

int main()
{
    int n;
    char s[maxn];
    int a[3],b[3],temp[maxn];
    cin>>n;
    cin>>s;
    memset(a,0,sizeof(a));
    for(int i=0; i0&&(t>temp[now+1]||a[t]==b[t]))//b[t]>0:'t'字符多
                                               //t>temp[now+1]:当前字典序大||a[t]==b[t]:'t'字符所剩的和多的数量相等
        {
            s[i]=temp[++now]+'0';
            b[t]--;
        }
        if(now==tot)//所有需要交换的都已完成
            break;
        a[t]--;
    }
    cout<

E:

输入一个数组a,构造一个数组b,原则是:

1:b1=0.

2:对于每一对1<=i,j<=n,如果ai​=aj​,那么bi​=bj​

3:对于每一个i∈[1,n−1],​或者

思路:

mp[i] 记录i最后出现的位置,right 记录 当前数字最后出现的位置。很显然如果两个数相等,那么他们中间这一段肯定都相等。

right也可理解为,当前位置到right位置的数字一定相同。当 i>right时,表明新数字出现,新的线段出现,答案×2.否则不变。

#include 
#include 
using namespace std;
typedef long long ll;
const int maxn = 2e5+5;
const int mod = 998244353;
map mp;
int a[maxn];
int main()
{
    int n;
    cin>>n;
    for(int i=1; i<=n; i++)
    {
        cin>>a[i];
        mp[a[i]]=i;
    }
    int right =1;
    ll ans=1;
    for(int i=1; i<=n; i++)
    {
        if(right>=i)
            right=max(right,mp[a[i]]);
        else
        {
            ans=ans*2%mod;
            right=max(right,mp[a[i]]);
        }
    }
    cout<

 

 

 F:

参考:https://blog.csdn.net/qq_38891827/article/details/86258302

你可能感兴趣的:(div3,cf)