Educational Codeforces Round 140 D

92 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第13天,点击查看活动详情

D - Playoff

题意:一共2n2^n个参赛选手,其能力值是[1,2n2^n]的排列。一共进行n轮比赛,每轮比赛都会与自己相邻的选手比赛比如[1,2],[3,4],,,然后胜者可以和相邻对的胜者进行比赛,n轮游戏过后会有一个选手成为冠军。给定一个长度为n的01串,s[i]=0表示在第i轮能力值较小的会获胜,否则能力值大的会获胜,求在所有可能的排列情况下有多少选手可能成为冠军
思路:一开始看样例的时候打了个表发现答案只和0的个数有关,和位置没啥关系,但是自己打的表n=4时太慢了,以为1出现的位置不同答案就会不同,然后就不知道该如何去想了,其实只是代码耗时太长了而已,可以拿样例来找一下规律,可以发现答案会是连续的一段区间,那么只要看出最小值和最大值的规律就可以了,s串中1的个数有x个,0的个数有y个,可以发现答案就是2x2^x~(2n2y+1)(2^n-2^y+1)

#include<bits/stdc++.h>
//#pragma-GCC-optimize("-Ofast");
#define ll long long
#define int long long
#define lowbit(x) ((x)&(-x))
#define endl '\n'
using namespace std;
typedef pair<int, int> PII;
typedef pair<double,double>PDD;
typedef pair<string,int>PSI;
typedef pair<string,PII>PSP;
const ll mod=998244353;
const ll inf=1e18;
const double pi=acos(-1);
const int N=1e6+100;
ll qpow(ll a,ll b)
{
    ll res=1;
    while(b)
    {
        if(b&1) res=res*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return res;
}
ll getinv(ll a){return qpow(a,mod-2);}
int n;
char s[22];
signed main()
{
    ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
    cin>>n;
    cin>>(s+1);
    int ze=0,one=0;
    for(int i=1;i<=n;i++)
        if(s[i]=='0') ze++;
        else one++;
    int minn=(1<<one),maxx=(1<<n)-(1<<ze)+1;
    for(int i=minn;i<=maxx;i++) cout<<i<<" ";
    return 0;
}