zoukankan      html  css  js  c++  java
  • AtCoder Grand Contest 012 C:Tautonym Puzzle

    题目传送门:https://agc012.contest.atcoder.jp/tasks/agc012_c

    题目翻译

    如果一个字符串是好的,那么这个字符串的前半部分和后半部分肯定一模一样。比如(aa)(bubobubo)就是好的串,而空串,(a)(abcabcabc)以及(abba)就不是好的。现在给你一个小于等于(10^{12})的数字(N),要你求出一个字符串(s),使得这个串的(2^{len}-1)个子串里刚好有(N)个子串是好的。要求(lenleqslant 200)

    题解

    我们先钦点空串是好的,(s=X+Y)(X)(Y)分别是子串里只有空串是好串的字符串。假设(c)并没有出现在(s)里,我们用两种方式将(c)添加进(s)里去:

    第一种:(s'=cX+Yc),这样的话(s')的子串里好串的数量会比(s)里多(1)

    第二种:(s'=Xc+Yc),这样的话(s')的子串里好串的数量会比(s)的多一倍。

    只需要加一和乘二两种操作就可以凑出所有的数,我们把(N)二进制分解一下用双端队列搞搞就可以了。

    时间复杂度:(O(logN))

    空间复杂度:(O(len))

    代码如下:

    #include <deque>
    #include <cstdio>
    using namespace std;
    typedef long long ll;
    
    int m,num;
    deque<int> s1,s2;
    deque<int>::iterator it;
    
    ll read() {
    	ll x=0,f=1;char ch=getchar();
    	for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
    	for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
    	return x*f;
    }
    
    int main() {
    	ll n=read()+1;//以为空串也是好串,所以这里要加一
    	for(ll i=1;i<=n;i<<=1)m++;
    	for(int i=m-2;~i;i--) {//初始有一个空串是好串,m-2是n的第二高的二进制位
    		s1.push_back(++num),s2.push_back(num);
    		if((n>>i)&1)s1.push_front(++num),s2.push_back(num);
    	}
    	printf("%d
    ",(int)(s1.size()+s2.size()));
    	for(it=s1.begin();it!=s1.end();it++)
    		printf("%d ",(*it));
    	for(it=s2.begin();it!=s2.end();it++)
    		printf("%d ",(*it));
    	return 0;
    }
    
  • 相关阅读:
    python学习
    androidandroid中的通过网页链接打开本地app
    Android自定义View之绘制虚线
    Backbone学习记录(3)
    Backbone学习记录(2)
    Backbone学习记录(1)
    网络时间轴中竖线的含义
    控制台笔记
    css hack 笔记
    Fiddler学习笔记
  • 原文地址:https://www.cnblogs.com/AKMer/p/10043220.html
Copyright © 2011-2022 走看看