cf708B. Recover the String---(构造法)

题目链接:http://codeforces.com/problemset/problem/708/B

意思是给出四个参数 
a00表01串中00对的数量 
a01表01串中01对的数量 
a10表01串中10对的数量 
a11表01串中11对的数量

求出一个符合条件的01串,如果不存在输出Impossible;

根据a00和a11可以求出0和1的个数;把cnt1个1放在前面,cnt0个0放在后面,此时的01串为0,当把0往前移动一位是01的个数会增加一,所以可以根据a01的个数移动0的位置;

当然在当a00为0时0的个数可能是0个也可能是1个要看a01和 a10同样1的个数也是一样;有对应的串时应满足1的个数*0的个数 = a01+a10的;

#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <queue>
#include <algorithm>
typedef long long LL;
#define INF 0x3f3f3f3f
#define N 1000100

using namespace std;

int a[4];
char ans[N];

int main()
{
    for(int i=0; i<4; i++)
        scanf("%d", &a[i]);

    if(!a[0] && !a[1] && !a[2] && !a[3])
    {
        printf("0\n");
        return 0;
    }

    int cnt0, cnt1;

    if(!a[0] && !a[1] && !a[2]) cnt0 = 0;
    else cnt0 = 1;

    if(!a[3] &&!a[1] && !a[2]) cnt1 = 0;
    else cnt1 = 1;

    if(a[0]) cnt0 = (int)sqrt(a[0]*2) + 1;
    if(a[3]) cnt1 = (int)sqrt(a[3]*2) + 1;

    if(a[0]*2 != cnt0*(cnt0-1) || a[3]*2 != cnt1*(cnt1-1) || cnt0*cnt1 != a[1]+a[2])
    {
        puts("Impossible");
        return 0;
    }

    int p = 0, r = 0;

    while(a[1])
    {
        if(a[1] >= cnt1)
        {
            ans[p++] = ‘0‘;
            a[1] -= cnt1;
            r++;
        }
        else
        {
            int m = cnt1-a[1];
            while(m) ans[p++] = ‘1‘, m--;
            ans[p++] = ‘0‘, r++;
            a[1] = 0;
        }
    }

    int s = p-r;
    while(cnt1-s) ans[p++] = ‘1‘, s++;
    while(cnt0-r) ans[p++] = ‘0‘, r++;

    puts(ans);

    return 0;
}

时间: 2024-08-02 18:25:23

cf708B. Recover the String---(构造法)的相关文章

CF708B Recover the String 构造

For each string s consisting of characters '0' and '1' one can define four integers a00, a01, a10 and a11, where axy is the number of subsequences of length 2 of the string s equal to the sequence {x,?y}. In these problem you are given four integers

生成子集 (增量构造法)

使用增量构造法可以构造出升序数组arr的不重复子集,并且按字典序排序 #include<bits/stdc++.h> using namespace std; int arr[16]; inline void print_subset(int *index, int cur, int n)///cur值这里可以理解为在这个堆栈层子集的集合数 { for(int i=0; i<cur; i++) {printf("%d ", arr[index[i]]);} if(cu

利用子集构造法实现NFA到DFA的转换

概述 NFA非有穷自动机,即当前状态识别某个转换条件后到达的后继状态不唯一,这种自动机不便机械实现,而DFA是确定有限状态的自动机,它的状态转换的条件是确定的,且状态数目往往少于NFA,所以DFA能够比较方便的机械实现且识别能力方面也和NFA相当.本次实验采用子集构造法来实现不带空弧的由NFA到DFA的转换. 子集构造法的算法如下: 设NFA为M=(K,Σ,f,S0,Z),则构造相应的DFA  M′=(Q,Σ,f′,I0,F)①取I0=S0:②对于状态集Q中任一尚未标记的状态qi={Si1,Si

C++ string 构造的陷阱

先看代码 #include<iostream> #include<string> using namespace std; int main(int argc, char **argv) { string s = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz" + 'A'; cout<<s<<endl; return 0; }

【算法竞赛入门经典】7.3子集生成【增量构造法】【位向量法】【二进制法】

7.3.1增量构造法 思路:一次选出一个元素放到集合中.自己对于递归的理解还是不够,这里虽然没有明确给出递归停止条件,但是如果无法继续添加元素,就不会再继续递归,然后就是我头疼的回溯啦. #include<stdio.h> int num[4],n; void A(int n,int *a,int ans) { for(int i = 0; i < ans; i ++)//打印当前元素 printf("%d ",a[i]); printf("\n"

子集生成——增量构造法+位向量法+二进制法

1.增量构造法: 原理图: 1 // 此算法仅用于输出下标,实际运用应输入另一个数组来进行数据的储存 2 #include <bits/stdc++.h> 3 using namespace std; 4 typedef long long ll; 5 typedef unsigned long long ull; 6 #define INF 0X3f3f3f3f 7 const ll MAXN = 1e3 + 7; 8 const ll MOD = 1e9 + 7; 9 int a[10];

Codeforces Round #276 (Div. 2)C. Bits(构造法)

这道题直接去构造答案即可. 对于l的二进制表示,从右到左一位一位的使其变为1,当不能再变了(再变l就大于r了)时,答案就是l. 这种方法既可以保证答案大于等于l且小于等于r,也可以保证二进制表示时的1最多. #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<cmath> #include&l

uva120 Stacks of Flapjacks (构造法)

这个题没什么算法,就是想出怎么把答案构造出来就行. 思路:越大的越放在底端,那么每次就找出还没搞定的最大的,把它移到当前还没定好的那些位置的最底端,定好的就不用管了. 这道题要处理好输入,每次输入的一行中是带空格的,以换行符结束一组数据的输入,那么用getline()函数.再用stringstream(这个可以自动转格式),非常方便的就处理了输入的问题.另外注意max_element和min_element都是左闭右开的. #include<iostream> #include<cstd

POJ 3295-Tautology(构造法+栈)

Tautology Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9936   Accepted: 3774 Description WFF 'N PROOF is a logic game played with dice. Each die has six faces representing some subset of the possible symbols K, A, N, C, E, p, q, r, s,