Educational Codeforces Round 86 (Rated for Div. 2) B C D题

Educational Codeforces Round 86 (Rated for Div. 2)

B. Binary Period

题意

给出一个01串t,让找到一个01串s,满足以下条件:

  1. 长度不超过2*|t|
  2. t是s的子序列
  3. s的周期尽可能的短

思路

如果t中全是0或者1,直接输出t。

否则输出|t|个01

代码

#include<bits/stdc++.h>
#define pb push_back
using namespace std;
const int N=2e5+10;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const double Pi=acos(-1.0);
typedef unsigned long long ull;
typedef long long ll;

char str[N];
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%s",str+1);
        int len=strlen(str+1);
        int sum=0;
        for(int i=1;i<=len;i++)
            sum+=str[i]-'0';
        if(sum==0||sum==len) printf("%s
",str+1);
        else{
            for(int i=1;i<=len;i++)
                printf("01");
            printf("
");
        }
    }
    return 0;
}

C. Yet Another Counting Problem

题意

给出两个整数a,b以及q个询问,每次询问给出区间[l,r],问在区间中有多少个数字x,
使得(x mod a mod b!= x mod b mod a)

思路

因为l,r非常大,先打了个1-1000中,a=3,b=5的时候相等的x的值可能是多少。

发现有规律。

0 1 2 3 4
15 16 17 18 19
30 31 32 33 34
45 46 47 48 49
60 61 62 63 64
75 76 77 78 79
90 91 92 93 94
105 106 107 108 109
120 121 122 123 124
135 136 137 138 139
150 151 152 153 154
165 166 167 168 169
180 181 182 183 184
195 196 197 198 199
210 211 212 213 214
225 226 227 228 229
240 241 242 243 244
255 256 257 258 259

每段开头都是a,b的最小公倍数的倍数,长度为(max(a,b))

代码

#include<bits/stdc++.h>
#define pb push_back
using namespace std;
const int N=2e5+10;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const double Pi=acos(-1.0);
typedef unsigned long long ull;
typedef long long ll;

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        ll a,b,q;
        scanf("%lld%lld%lld",&a,&b,&q);
        if(a>b) swap(a,b);
        ll lcm=a*b/__gcd(a,b);
        while(q--)
        {
            ll l,r;
            scanf("%lld%lld",&l,&r);
            ll lpos=l/lcm,rpos=r/lcm;
            ll lst=lpos*lcm,len=lst+b-1;
            ll rst=rpos*lcm,ren=rst+b-1;
            ll ans=0;
            if(lpos==rpos)
            {
                ans=max((ll)0,min(r,len)-max(l,lst)+1);
            }
            else
            {
                ans+=max((ll)0,len-l+1)+min(r,ren)-rst+1;
                ans+=(rpos-lpos-1)*b;
            }
            printf("%lld ",r-l+1-ans);
        }
        printf("
");
    }
    return 0;
}

D. Multiple Testcases

题意

给出n个数字,最大的数字为k,然后现在要把这n个数字,分到x个数组中,每个数字中都要满足>=i的数字的数量不能超多(c_i),问x的最小值。

思路

直接模拟放。

对n个数字排序,如果从前往后放不好判断题目中的限制条件,我们从后往前放。

假如当前数字为(x),那么一个数组中大于等于它的数字最多有(c_x-1)个,我们只能放到此时数组大小小于(c_x)的数组中。

寻找数组的过程如果遍历复杂度太高,考虑使用二分。

我们要让数组的大小是一个有序的序列,那么每次放的时候优先放到数组中下标小的,如果没有找到合适的,

新建一个数组。

这样这些数组的大小是递减的。就可以使用二分查找当前数字该放到哪个数组中。

代码

#include<bits/stdc++.h>
#define pb push_back
using namespace std;
const int N=2e5+10;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const double Pi=acos(-1.0);
typedef unsigned long long ull;
typedef long long ll;

int arr[N],lim[N],vis[N],tmp[N];
vector<int>vec[N];
int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) scanf("%d",&arr[i]);
    for(int i=1;i<=m;i++) scanf("%d",&tmp[i]);
    sort(arr+1,arr+1+n);
    for(int i=1;i<=n;i++)
        lim[i]=tmp[arr[i]];
    int cnt=1;
    for(int i=n;i;i--)
    {
        int l=1,r=cnt-1,ans=-1;
        while(l<=r)
        {
            int mid=(l+r)/2;
            if(vec[mid].size()<lim[i])
            {
                ans=mid;
                r=mid-1;
            }
            else l=mid+1;
        }
        if(ans==-1)vec[cnt++].pb(arr[i]);
        else vec[ans].pb(arr[i]);
    }
    printf("%d
",cnt-1);
    for(int i=1;i<cnt;i++)
    {
        printf("%d ",(int)vec[i].size());
        for(int v:vec[i]) printf("%d ",v);
        printf("
");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/valk3/p/13084223.html