Codeforces Round #572(Div.2)

目录

A - Keanu Reeves

B - Number Circle

C - Candies!

D - Add on a Tree

E - Count Pairs


A - Keanu Reeves

题意:一个01字符串S,把它分成K段,使得每段的0的数量不等于1的数量,让K尽可能的小。

输出分成的段数和分完后的K段。

思路:

如果0和1的数量不等,分成一段;相等,分成两段。s[0]s[1]\rightarrow s[n-1]

AC代码:

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n;
    string s;
    cin>>n;
    cin>>s;
    int cnt0=0,cnt1=0;
    for(int i=0;i<n;i++)
    {
        if(s[i]=='0')
            cnt0++;
        else
            cnt1++;
    }
    if(cnt0!=cnt1)
    {
        cout<<"1"<<endl;
        cout<<s<<endl;
    }
    else
    {
        cout<<"2"<<endl;
        cout<<s[0]<<" ";
        for(int i=1;i<n;i++)
            cout<<s[i];
        cout<<endl;
    }
}

B - Number Circle

题意:给你n个数,用这n个数构造一个序列,使得它们围成圆圈后,每个数都严格小于左右邻居的和。

思路:

对数组排序。

如果a[n]\geq a[n-1]+a[n-2]则不行,其他情况都可以。

对数组排完序后,除了1和n之外,其他的点都可以满足条件。因为a[i]\leqslant a[i+1],所以一定a[i]<a[i+1]+a[i-1]。但是a[n]不一定小于a[1]+a[n-1]。所以,我们让a[n]a[n-1]交换位置。

AC代码:

#include<bits/stdc++.h>
using namespace std;
const int maxx=1e5+10;
int a[maxx];
int main()
{
   int n;
   cin>>n;
   for(int i=1;i<=n;i++)
   {
       cin>>a[i];
   }
   sort(a+1,a+1+n);
   if(a[n]>=(a[n-1]+a[n-2]))
      cout<<"NO"<<endl;
   else
   {
       cout<<"YES"<<endl;
       cout<<a[n]<<" "<<a[n-1];
       for(int i=1;i<=n-2;i++)
       {
           cout<<" "<<a[i];
       }
       cout<<endl;
   }
}

C - Candies!

题意:给你一个数组a(0\leqslant a_{i}\leqslant 9),m个区间,每个区间的长度2^{k}

有一种操作是把奇数位和偶数位相加  用和来代替之前的两个数。如果和大于等于10就要%10,并且答案计数+1  。每一个区间奇数位和偶数位不断相加取模处理。问最后只剩一个数的时候,取了几次模。

思路:

每一个区间最后都是操作到只剩一位的,因为0\leqslant a_{i}\leqslant 9,每次操作都有一个10答案数加1,可以直接将区间的值累和,判断总和可以有几个10。所以直接前缀和然后再除10。

 AC代码:

#include<bits/stdc++.h>
using namespace std;
const int maxx=1e5+10;
int a[maxx];
int sum[maxx];
int main()
{
    int n,m,l,r;
    memset(sum,0,sizeof(sum));
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        sum[i]=sum[i-1]+a[i];
    }
    cin>>m;
    while(m--)
    {
        cin>>l>>r;
        int ans=(sum[r]-sum[l-1])/10;
        cout<<ans<<endl;
    }
}

D - Add on a Tree

题意:给你一棵有n个节点的树。一开始,所有的边都是0。在一个操作中,你可以选择任意2个不同的叶子u, v和任何实数x,并将x加到u和v之间路径上的所有边上。问,是否可以实现构造后的树让每一条边都为任意值。

思路:

 样例二解释:选取任意的两个叶子节点,这个样例只能选择1和3,这两个节点连接的边都加x,

 不论怎么加,这两条边的值都相等,这两条边就像绑定了,不能实现让任一条边为任意值。

 样例三解释:选取任意的两个叶子节点3,4之后,(3,1)(4,1)权值相等了,但是可以通过(5,2,1,4)加个x,使得(3,1)(4,1)的权值不等,可见,当一个顶点连接三条边的时候可以实现让任一条边为任意值。但是,该样例中(5,2)(2,1)具有绑定关系,我要经过2顶点,必须同时走(5,2)(2,1)。

 

如果一个节点有两条边,它肯定不是叶子节点,向下可以找到至少一个叶子节点,形成集合U(如图中7),向上可以找到其他的叶节点(如4,5,6)形成集合V。U,V交集为空。

任意U中的的叶节点到V都只能经过刚刚找到的节点相连的两条边,所以这两条边边权相等。

AC代码:

#include<bits/stdc++.h>
using namespace std;
const int maxx=1e5+10;
int d[maxx];
int main()
{
    int n,u,v;
    cin>>n;
    memset(d,0,sizeof(d));
    for(int i=1;i<n;i++)
    {
        cin>>u>>v;
        d[v]++;
        d[u]++;
    }
    int f=0;
    for(int i=1;i<=n;i++)
    {
        if(d[i]==2)
        {
            f=1;
        }
    }
    if(f==1)
        cout<<"NO"<<endl;
    else
        cout<<"YES"<<endl;
}

E - Count Pairs

题意:

思路:

                                              (a_{i}+a_{j})(a_{i}^{2}+a_{j}^{2})%p\equiv k%p

两边同时乘(a_{i}-a_{j}):                           (a_{i}^{4}-a_{j}^{4})%p\equiv (a_{i}^{}-a_{j}^{})*k%p

移项:                                                  (a_{i}^{4}-ka_{i})%p\equiv (a_{j}^{4}-ka_{j})%p

遍历,求x^4%p-k*x%p,前面出现过几个与该值相等的ans就累加次数(map)。

注意x^4%p-k*x%p可能小于零,所以要加个p。

AC代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
map<ll,ll>m;
int main()
{
    ll n,p,k,x,tmp;
    ll ans=0;
    cin>>n>>p>>k;
    for(int i=0;i<n;i++)
    {
        cin>>x;
        tmp=x*x%p*x%p*x%p;
        tmp=(tmp-(k*x%p)+p)%p;
        ans+=m[tmp];
        m[tmp]++;
    }
    cout<<ans<<endl;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值