Codeforces Round #247 (Div. 2) - Random Task

数位DP+二分答案

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define MOD ((int)(1e9) + 7)
#define eps 1e-10
using namespace std;
typedef long long ll;
#define maxn 64
#define INF 1000000000000000000LL
ll C[maxn][maxn];
ll bit(ll mask, ll i) {
    return (mask>>i)&1;
}
int bit_count(ll x) {
    int cnt = 0;
    while (x) {
        cnt ++;
        x &= (x-1);
    }
    return cnt;
}
ll dp(ll n, ll k) {
    ll cnt = 0;
    if (k == bit_count(n)) {
        cnt ++;
    }
    for (int i = maxn-1; i >= 0 && k>=0; -- i) {
        if (bit(n,i)) {
            cnt += C[i][k--];
        }
    }
    return cnt;
}
ll m, k;
int main() {
    C[0][0] = 1;
    for (int i = 1; i <= maxn-1; ++ i) {
        for (int j = 0; j <= i; ++ j) {
            C[i][j] = C[i-1][j] + ((j)?(C[i-1][j-1]):0);
        }
    }
    while(cin >> m >> k) {
        ll L = 1, R = INF, M = 1;
        while (L < R) {
            M = (R + L) / 2;
            if (dp(2*M,k) - dp(M,k) < m) L = M+1; // [1,2*M] - [1,M] = [M+1,2*M]
            else R = M;
        }
        cout << L << endl;
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值