[agc012c]Tautonym Puzzle

前言

怎么wxh随手秒的傻逼题我看了好多眼啊。
对于这种题我感到措手不及,因为这样的题我一般只会两种方法。
一种是分离构造,将答案序列分成若干个互不相干的部分,答案是这些部分答案的和。
那么只要我能想到如何简单构造一个部分即可。
可惜我这样想长度怎么都爆。
另一种是倍增构造,但是想了好久都不知道如何不长度*2的把答案*2。
这就很GG了。
最后总结一下我的想题过程,这样的题还是朝着二进制拆分方案(有些构造题是分解质因数)去思考的,只要能构造出一个2^t即可,而且要让这些2^t加起来。
看起来是分离构造,我想了一会儿才想到怎么不分离。
确实构造弱。。

题意

构造一个长度在200以内每个元素在100以内的字符串。
使得对于其一个子序列子串,若非空且可以表示成AA的形式,ans便+1,最后ans等于S。

构造

先找到一个最大的m使得 2m<=S
那么先构造一个1 2 3……m 1 2 3……m m+1 m+1
这样显然方案数为 2m
然后对于每个S剩余的二进制位t,你都需要一个 2t
你可以把一个从未出现的数字塞的前半部分的t后面,然后把同样的数字塞到最末尾。
你需要按位数从大到小做,以确保这些零散数字之间不形成合法字符串。
然后就行了。

#include<cstdio>
#include<algorithm>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
typedef long long ll;
ll two[50+5],s;
int a[210],b[50+5],c[210];
int i,j,k,l,t,n,m,mx,tot,top,now;
int main(){
    //freopen("data.out","w",stdout);
    scanf("%lld",&s);
    two[0]=1;
    fo(i,1,50) two[i]=(ll)two[i-1]*2;
    mx=50;
    while (two[mx]>s) mx--;
    s-=two[mx];
    m=mx;
    tot=2*m;
    now=m;
    c[++top]=now+1;
    c[++top]=now+1;
    now++;
    tot+=2;
    while (s){
        while (two[mx]>s) mx--;
        s-=two[mx];
        b[mx]=++now;
        c[++top]=now;
        tot+=2;
    }
    printf("%d\n",tot);
    fo(i,0,m){
        if (i) printf("%d ",i);
        if (b[i]) printf("%d ",b[i]);
    }
    fo(i,1,m) printf("%d ",i);
    fo(i,1,top) printf("%d ",c[i]);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值