Google kickstart 2018 RoundB Sherlock and the Bit Strings

题目链接

这道题目我自己看了官方题解还是写不出来,于是乎查阅了老哥的题解,这里就不班门弄斧了,这老哥写的已经很完美了。

带佬的解析

附上烂代码

#include<bits/stdc++.h>
#define popcnt(a) __builtin_popcount(a)
using namespace std;
typedef unsigned int ui;
typedef long long ll;
typedef pair<int,int> pii;
int n,k;
ll p;
ll dp[1 << 16][102];
vector<pii> R[102];
bool ok(ui num,int id)
{
    for(int i = 0;i < R[id].size();i++)
    {
        int lmt = id - R[id][i].first + 1;
        ui mask = num & ((1 << lmt)-1);
        //cout << num << " " << R[id][i].first << " " << id << " " << R[id][i].second << " " << popcnt(mask) << endl;
        if(popcnt(mask)!= R[id][i].second)
            return false;
    }
    return true;
}
ll solve(ui num,int id)
{
    //cout << num  << " " << id << endl;
    if(dp[num][id] != -1)
        return dp[num][id];
    if(!ok(num,id))
        return dp[num][id] = 0;
    if(id == n)
        return dp[num][id] = 1;
    ui next = (num << 1) & 0xffff;
    ll ret = 0;
    ret += solve(next,id+1);
    if(ret < p)
        ret += solve(next|1,id+1);
    if(ret > p)
        ret = p;
    return dp[num][id] = ret;
}
int main()
{
    int t;
    cin >> t;
    for(int kase = 1;kase <= t;kase++)
    {
        string ans;
        memset(dp,-1,sizeof(dp));
        for(int i = 1;i < 102;i++)
            R[i].clear();
        cin >> n >> k >> p;
        for(int i = 0; i < k;i++)
        {
            int l,r,c;
            cin >> l >> r >>c;
            R[r].push_back(make_pair(l,c));
        }
        solve(0,0);
        ui mask = 0;
        for(int i = 1;i <= n;i++)
        {
            mask = (mask << 1) & 0xffff;
            if(dp[mask][i] >= p)
            {

                ans+='0';
            }
            else
            {
                p-=dp[mask][i];
                mask |= 1;
                ans += '1';
            }
        }
        printf("Case #%d: %s\n",kase,ans.c_str());
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值