CodeForces 708B Recover the String

构造。

根据$a[0][0]$可以求得$0$的个数$p$,根据$a[1][1]$可以求得$1$的个数$q$。 如果找不到$p$或$q$,那么就无解。

每一个$0$放到序列中的任何一个位置,假设和前面的$1$产生了$x$对$10$,和后面的$1$产生了$y$对$01$,那么$x+y$一定等于$q$。

也就是说如果$p*q$不等于$a[0][1]+a[1][0]$,那么就无解了。否则只要将$1$一个一个放进序列中,凑成$1$前面的$0$的个数总和是$a[0][1]$就可以了。

上面的方法对一般的情况都是成立的,对于三种特殊情况需要特判一下:$[1].$$0$ $0$ $0$ $0$   $[2].$$0$ $0$ $0$ $X$   $[3].$$X$ $0$ $0$ $0$。

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<iostream>
using namespace std;
typedef long long LL;
const double pi=acos(-1.0),eps=1e-8;
void File()
{
    freopen("D:\\in.txt","r",stdin);
    freopen("D:\\out.txt","w",stdout);
}
template <class T>
inline void read(T &x)
{
    char c = getchar(); x = 0;while(!isdigit(c)) c = getchar();
    while(isdigit(c)) { x = x * 10 + c - ‘0‘; c = getchar();  }
}

LL p=-1,q=-1,a[2][2];
int pos[1000010];

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

    for(LL i=1;i*(i-1)<=2*a[0][0];i++)
        { if(i*(i-1)==2*a[0][0]) { p=i; break;} }

    for(LL i=1;i*(i-1)<=2*a[1][1];i++)
        { if(i*(i-1)==2*a[1][1]) { q=i; break;} }

    if(p==-1||q==-1) { printf("Impossible\n"); return 0; }

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

    if(a[0][0]==0&&a[0][1]==0&&a[1][0]==0&&a[1][1]!=0)
        {for(int i=1;i<=q;i++) printf("1"); printf("\n"); return 0;}

    if(a[0][0]!=0&&a[0][1]==0&&a[1][0]==0&&a[1][1]==0)
        { for(int i=1;i<=p;i++) printf("0"); printf("\n"); return 0; }

    if(p==-1||q==-1) printf("Impossible\n");
    else if(p+q>1000000) printf("Impossible\n");
    else if(p*q!=a[0][1]+a[1][0]) printf("Impossible\n");
    else
    {
        for(int i=1;i<=p;i++)
        {
            if(q>=a[1][0]) pos[a[1][0]]++,a[1][0]=0;
            else pos[q]++,a[1][0]=a[1][0]-q;
        }
        for(int i=1;i<=pos[0];i++)printf("0");
        for(int i=1;i<=q;i++)
        {
            printf("1");
            for(int j=1;j<=pos[i];j++) printf("0");
        }
        printf("\n");
    }
    return 0;
}
时间: 2024-10-29 19:11:44

CodeForces 708B Recover the String的相关文章

Educational Codeforces Round 25 F. String Compression(kmp+dp)

题目链接:Educational Codeforces Round 25 F. String Compression 题意: 给你一个字符串,让你压缩,问压缩后最小的长度是多少. 压缩的形式为x(...)x(...)  x表示(...)这个出现的次数. 题解: 考虑dp[i]表示前i个字符压缩后的最小长度. 转移方程解释看代码,这里要用到kmp来找最小的循环节. 当然还有一种找循环节的方式就是预处理lcp,然后通过枚举循环节的方式. 这里我用的kmp找的循环节.复杂度严格n2. 1 #inclu

Codeforces 56D Changing a String 编辑距离 dp

题目链接:点击打开链接 编辑距离,,== 一边dp一边记录前驱太累,,还是dp后找路径大法好 #include<iostream> #include<cstdio> #include<vector> #include<string.h> using namespace std; #define ll int #define N 1010 char s[N], t[N]; int dp[N][N], n, m; // 0为插入 1为删除 2 3为替换 stru

【题解】Recover the String Codeforces 708B

题解讲的不是很详细,有些定理未加证明地直接给出,需要读者自己思考,如有不懂欢迎在讨论区提问 由00和11的个数可以确定0和1的个数假设00的个数是b,必须满足a*(a-1)/2=b,且a是整数这时候,a便是0的个数,求1的个数同理同时,01和10的个数的和 一定是 0的个数*1的个数然后构造一个00000000001111111111这样的串,是不存在10这样的子序列的我们称最右边的一坨1叫"没有交换的1",然后每次选择这里面最左边的一个1和第x(x待确定)个0交换注意到,和第x个0交

【最短路】Codeforces 710E Generate a String

题目链接: http://codeforces.com/problemset/problem/710/E 题目大意: 问写N个字符的最小花费,写一个字符或者删除一个字符花费A,将当前的字符数量翻倍花费B. 题目思路: [动态规划][最短路] [动态规划]: 如果当前x不是2的倍数,那么一定需要单个字符增加或删除,而这个单个操作越靠后答案越优. dp(x)=a+min(dp(x-1),dp(x+1)) 如果当前x是2的倍数,那么有两种情况,一种是通过翻倍的方式获得,一种是通过累加的方式获得.只要比

(DP)codeforces - 710E Generate a String

原题链接:http://www.codeforces.com/problemset/problem/710/E 题意:一个字符串,开始长度为0,目标长度为n,长度+1或-1需要的时间为x,长度*2需要的时间为y,求0到m需要的最少时间. 分析:这题一上来直接写优先队列bfs,然后很愉快的超内存的了.就想别的方法,想了一会没想清晰,感觉可以用记忆化搜索,就往这上面一想,才发现直接dp就行了. 可以很容易发现,奇数肯定是+1或者通过*2逼近并且+1或-1得到. 而偶数只能在+1和翻倍得到. 所以在奇

CodeForces B. Obtaining the String

http://codeforces.com/contest/1015/problem/B You are given two strings ss and tt. Both strings have length nn and consist of lowercase Latin letters. The characters in the strings are numbered from 11 to nn. You can successively perform the following

[ An Ac a Day ^_^ ] CodeForces 525B Pasha and String 技巧

题意就是一次次翻转字符串 然后输出最终的字符串 暴力一发O(n*m)果然超时了 因为每次翻转的的都是a-1到对称位置 所以一个位置翻转两次等于没有操作 所以只需要记录一下len/2的位置前的操作次数 O(len/2)…… 1 #include<stdio.h> 2 #include<iostream> 3 #include<algorithm> 4 #include<math.h> 5 #include<string.h> 6 #include&

codeforces 623A. Graph and String 构造

题目链接 给出一个图, 每个节点只有三种情况, a,b, c. a能和a, b连边, b能和a, b, c,连边, c能和b, c连边, 且无重边以及自环.给出初始的连边情况, 判断这个图是否满足条件. 由题意可以推出来b必然和其他的n-1个点都有连边, 所以初始将度数为n-1的点全都编号为b. 然后任选一个与b相连且无编号的点, 编号为1. 然后所有与1无连边的点都是3. 然后O(n^2)检查一下是否合理. #include <iostream> #include <vector>

CodeForces 710E Generate a String (DP)

题意:给定 n,x,y,表示你要建立一个长度为 n的字符串,如果你加一个字符要花费 x时间,如果你复制前面的字符要花费y时间,问你最小时间. 析:这个题,很明显的DP,dp[i]表示长度为 i 的字符串的最少花费,当 i 是偶数时,要么再加一个字符,要么从i/2中复制,如果为奇数,要么再加1个字符, 要么从i/2先加一个,再复制.即: 奇数 : dp[i] = min(dp[i-1]+x, dp[i/2+1]+y+x); 偶数 : dp[i] = min(dp[i-1]+x, dp[i/2]+y