• CF431D Random Task 二分+数位dp


    One day, after a difficult lecture a diligent student Sasha saw a graffitied desk in the classroom. She came closer and read: "Find such positive integer n, that among numbers n + 1, n + 2, ..., n there are exactly m numbers which binary representation contains exactly k digits one".

    The girl got interested in the task and she asked you to help her solve it. Sasha knows that you are afraid of large numbers, so she guaranteed that there is an answer that doesn't exceed 1018.

    Input

    The first line contains two space-separated integers, m and k (0 ≤ m ≤ 1018; 1 ≤ k ≤ 64).

    Output

    Print the required number n (1 ≤ n ≤ 1018). If there are multiple answers, print any of them.

    Examples
    Input
    Copy
    1 1
    Output
    Copy
    1
    Input
    Copy
    3 2
    Output
    Copy
    5

    抱歉,我太菜了,只会二分来数位dp解决;
    貌似有题解是用组合数学解决的,orz ;
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstdlib>
    #include<cstring>
    #include<string>
    #include<cmath>
    #include<map>
    #include<set>
    #include<vector>
    #include<queue>
    #include<bitset>
    #include<ctime>
    #include<deque>
    #include<stack>
    #include<functional>
    #include<sstream>
    
    //#include<cctype>
    //#pragma GCC optimize("O3")
    using namespace std;
    #define maxn 1000005
    #define inf 0x3f3f3f3f
    #define INF 9999999999
    #define rdint(x) scanf("%d",&x)
    #define rdllt(x) scanf("%lld",&x)
    #define rdult(x) scanf("%lu",&x)
    #define rdlf(x) scanf("%lf",&x)
    #define rdstr(x) scanf("%s",x)
    typedef long long  ll;
    typedef unsigned long long ull;
    typedef unsigned int U;
    #define ms(x) memset((x),0,sizeof(x))
    const long long int mod = 1e9 + 7;
    #define Mod 1000000000
    #define sq(x) (x)*(x)
    #define eps 1e-3
    typedef pair<int, int> pii;
    #define pi acos(-1.0)
    //const int N = 1005;
    #define REP(i,n) for(int i=0;i<(n);i++)
    
    inline ll rd() {
    	ll x = 0;
    	char c = getchar();
    	bool f = false;
    	while (!isdigit(c)) {
    		if (c == '-') f = true;
    		c = getchar();
    	}
    	while (isdigit(c)) {
    		x = (x << 1) + (x << 3) + (c ^ 48);
    		c = getchar();
    	}
    	return f ? -x : x;
    }
    
    ll gcd(ll a, ll b) {
    	return b == 0 ? a : gcd(b, a%b);
    }
    ll sqr(ll x) { return x * x; }
    
    /*ll ans;
    ll exgcd(ll a, ll b, ll &x, ll &y) {
    	if (!b) {
    		x = 1; y = 0; return a;
    	}
    	ans = exgcd(b, a%b, x, y);
    	ll t = x; x = y; y = t - a / b * y;
    	return ans;
    }
    */
    
    
    
    ll qpow(ll a, ll b, ll c) {
    	ll ans = 1;
    	a = a % c;
    	while (b) {
    		if (b % 2)ans = ans * a%c;
    		b /= 2; a = a * a%c;
    	}
    	return ans;
    }
    /*
    int n, m;
    int st, ed;
    struct node {
    	int u, v, nxt, w;
    }edge[maxn<<1];
    
    int head[maxn], cnt;
    
    void addedge(int u, int v, int w) {
    	edge[cnt].u = u; edge[cnt].v = v; edge[cnt].w = w;
    	edge[cnt].nxt = head[u]; head[u] = cnt++;
    }
    
    int rk[maxn];
    
    int bfs() {
    	queue<int>q;
    	ms(rk);
    	rk[st] = 1; q.push(st);
    	while (!q.empty()) {
    		int tmp = q.front(); q.pop();
    		for (int i = head[tmp]; i != -1; i = edge[i].nxt) {
    			int to = edge[i].v;
    			if (rk[to] || edge[i].w <= 0)continue;
    			rk[to] = rk[tmp] + 1; q.push(to);
    		}
    	}
    	return rk[ed];
    }
    int dfs(int u, int flow) {
    	if (u == ed)return flow;
    	int add = 0;
    	for (int i = head[u]; i != -1 && add < flow; i = edge[i].nxt) {
    		int v = edge[i].v;
    		if (rk[v] != rk[u] + 1 || !edge[i].w)continue;
    		int tmpadd = dfs(v, min(edge[i].w, flow - add));
    		if (!tmpadd) { rk[v] = -1; continue; }
    		edge[i].w -= tmpadd; edge[i ^ 1].w += tmpadd; add += tmpadd;
    	}
    	return add;
    }
    ll ans;
    void dinic() {
    	while (bfs())ans += dfs(st, inf);
    }
    */
    
    ll dp[100][100], m;
    int num[100], len, k;
    
    ll dfs(int pos, int limit, int sum) {
    	if (pos < 0)return sum == k;
    	if (!limit&&dp[pos][sum] != -1)return dp[pos][sum];
    	ll ans = 0;
    	int up = limit ? num[pos] : 1;
    	for (int i = 0; i <= up; i++) {
    		ans += dfs(pos - 1, limit&&i == up, sum + (i == 1));
    	}
    	if (!limit)dp[pos][sum] = ans;
    	return ans;
    }
    
    ll sol(ll x) {
    	len = 0;
    	while (x) {
    		num[len++] = x % 2; x /= 2;
    	}
    	return dfs(len - 1, 1, 0);
    }
    
    int main()
    {
    	//ios::sync_with_stdio(0);
    	//memset(head, -1, sizeof(head));
    	while (cin >> m >> k) {
    		ll l = 1, r = 1000000000000000000;
    		memset(dp, -1, sizeof(dp));
    		while (l <= r) {
    			ll mid = (l + r) / 2;
    			ll res = sol(2 * mid) - sol(mid);
    			if (res == m) {
    				l = mid; break;
    			}
    			else if (res < m)l = mid + 1;
    			else r = mid - 1;
    		}
    		cout << l << endl;
    	}
        return 0;
    }
    
    
    
    EPFL - Fighting
  • 相关阅读:
    搜狗输入法用户体验评价
    第二阶段团队冲刺5
    第二阶段团队冲刺4
    进度总结报告十四
    第二阶段团队冲刺3
    寻找水王-课上练习
    第二阶段团队冲刺2
    大型网站处理高并发要点技术
    php 处理上百万条的数据库如何提高处理查询速度
    php一次性大量数据入库解决方法
  • 原文地址:https://www.cnblogs.com/zxyqzy/p/10050745.html
Copyright © 2020-2023  润新知