问题描述
作为一个神秘的电脑高手,Farmer John 用二进制数字标识他的奶牛。然而,他有点迷信,标识奶牛用的二进制数字,必须只含有 K 位“1”(1 <= K <= 10)。 当然,每个标识数字的首位必须为“1”。FJ 按递增的顺序,安排标识数字,开始是最小可行的标识数字(由“1”组成的一个 K 位数)。不幸的是,他没有记录下标识数字。请帮他计算,第 N 个标识数字(1 <= N <= 10^7)。

输入
第 1 行:空格隔开的两个整数,N 和 K。

输出
如题,第 N 个标识数字

输入输出样例
7 3

10110

思路

我思路真的很复杂(因为我太蒻了),不过有一些是很有价值的思想

就以样例做比方,其前几个排列是:

  111
1011
1101
1110
10011
10101
10110
11001
11100 ......

除了第一个,我们发现,把相同长度的分为一组,第i组内的大小为C(2+i,i)  [扩展到整道题就是C( k-1+i , i )]

我们就可以通过组合数的方式快速找到第n个数属于第几组

而在某一组内如何快速找到它的位置呢?

我们就数据中长度为5的那一组分析,抛开开头的1,0的位置依次为

1 2  1 3  1 4  2 3  2 4  3 4

也就是求C(2+i,i)中字典序大小的第m项 (设第n个数在这一组排第m项)

显然一项一项枚举是会T掉的,那我们可以怎样判断出某一位是几?

我们设总共有L个数字可选,D个位置可填,该位填的数字为i,现在填的第step位  (例子中L=4 D=2)

那么step位填i后,后面可填的方案数为C(L-i,D-step)

如果C>=m,说明这一位就填i,下一位就从i+1开始搜

否则这一位肯定不填i,m-=C后,继续判断该位是否填i+1

这样,我们就可以以近乎O(L)地判断出来第m项了。

Code

 #include<set>
#include<map>
#include<queue>
#include<stack>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define inf (1<<30)
#define ll long long
#define RG register int
#define rep(i,a,b) for(RG i=a;i<=b;i++)
#define per(i,a,b) for(RG i=a;i>=b;i--)
#define maxn 1000005
#define lim 1000002
using namespace std;
ll N,k,cnt,dep,numlim;
int pri[maxn],p[maxn],vis[maxn];
ll rec[][];
inline ll read()
{
ll x=,f=;char c=getchar();
while(c<''||c>''){if(c=='-')f=-;c=getchar();}
while(c>=''&&c<=''){x=x*+c-'';c=getchar();}
return x*f;
} void pre()
{
rep(i,,lim)
{
if(!pri[i]) p[++cnt]=i;
for(RG j=;j<=cnt&&i*p[j]<=lim;j++)
{
pri[i*p[j]]=;if(!(i%p[j])) break;
}
}
} ll work(ll x,ll p)
{
ll res=;
while(x) res+=x/p,x/=p;
return res;
} ll QP(ll a,ll mi)
{
ll ans=;
while(mi)
{
if(mi&) ans*=a;
a*=a;
mi>>=;
}
return ans;
} ll cnm(ll n,ll m)
{
ll ans=;
for(RG i=;p[i]<=n;i++)
{
ll _1=work(n,p[i]);
ll _2=work(m,p[i]);
ll _3=work(n-m,p[i]);
ans*=QP(p[i],_1-_2-_3);
}
return ans;
} void pt()
{
cout<<;
rep(i,,numlim)
{
printf("%d",!vis[i]);
}
exit();
} void dfs(int step,int st)
{
if(step>dep)
{
pt();
return;
}
for(int i=st;i<=numlim;i++)
{
int nn=numlim-i,mm=dep-step,cc;
if(rec[nn][mm]) cc=rec[nn][mm];
else rec[nn][mm]=cc=cnm(nn,mm);
if(cc<N){N-=cc;continue;}
vis[i]=;
dfs(step+,i+);
vis[i]=;
}
} void work()
{
if(N==){rep(i,,k)cout<<;return;}--N;
for(register ll i=k,j=;;++i,++j)
{
ll C=cnm(i,j);rec[i][j]=C;
if(C>=N) {numlim=i,dep=j;break;}
N-=C;
}
dfs(,);
} void work1()
{
cout<<;rep(i,,N) printf(""); exit();
} int main()
{
N=read(),k=read();
if(k==) work1();
pre();
work();
return ;
}

奶牛编号(Cowids) [NOIP模拟]的更多相关文章

  1. 【NOIP2012模拟8.7】JZOJ2020年8月8日提高组T1 奶牛编号

    [NOIP2012模拟8.7]JZOJ2020年8月8日提高组T1 奶牛编号 题目 作为一个神秘的电脑高手,Farmer John 用二进制数字标识他的奶牛. 然而,他有点迷信,标识奶牛用的二进制数字 ...

  2. NOIP模拟赛20161022

    NOIP模拟赛2016-10-22 题目名 东风谷早苗 西行寺幽幽子 琪露诺 上白泽慧音 源文件 robot.cpp/c/pas spring.cpp/c/pas iceroad.cpp/c/pas ...

  3. NOIP模拟赛 by hzwer

    2015年10月04日NOIP模拟赛 by hzwer    (这是小奇=> 小奇挖矿2(mining) [题目背景] 小奇飞船的钻头开启了无限耐久+精准采集模式!这次它要将原矿运到泛光之源的矿 ...

  4. 【noip模拟赛5】细菌 状压dp

    [noip模拟赛5]细菌   描述 近期,农场出现了D(1<=D<=15)种细菌.John要从他的 N(1<=N<=1,000)头奶牛中尽可能多地选些产奶.但是如果选中的奶牛携 ...

  5. NOI.AC NOIP模拟赛 第五场 游记

    NOI.AC NOIP模拟赛 第五场 游记 count 题目大意: 长度为\(n+1(n\le10^5)\)的序列\(A\),其中的每个数都是不大于\(n\)的正整数,且\(n\)以内每个正整数至少出 ...

  6. NOI.AC NOIP模拟赛 第三场 补记

    NOI.AC NOIP模拟赛 第三场 补记 列队 题目大意: 给定一个\(n\times m(n,m\le1000)\)的矩阵,每个格子上有一个数\(w_{i,j}\).保证\(w_{i,j}\)互不 ...

  7. NOIP模拟题汇总(加厚版)

    \(NOIP\)模拟题汇总(加厚版) T1 string 描述 有一个仅由 '0' 和 '1' 组成的字符串 \(A\),可以对其执行下列两个操作: 删除 \(A\)中的第一个字符: 若 \(A\)中 ...

  8. 【HHHOJ】NOIP模拟赛 玖 解题报告

    点此进入比赛 得分: \(100+20+100=220\)(还不错) 排名: \(Rank\ 16\) \(Rating\):\(+20\) \(T1\):[HHHOJ263]「NOIP模拟赛 玖」三 ...

  9. 【HHHOJ】NOIP模拟赛 捌 解题报告

    点此进入比赛 得分: \(30+30+70=130\)(弱爆了) 排名: \(Rank\ 22\) \(Rating\):\(-31\) \(T1\):[HHHOJ260]「NOIP模拟赛 捌」Dig ...

随机推荐

  1. robocopy的用法,数据库局域网备份

    robocopy,我主要是用来进行局域网数据库备份使用,不得不说这个小工具速度还是蛮快的,同时属于系统内置功能,用着还算方便. 这项功能就是RoboCopy,它是一个命令行的目录复制命令,自从Wind ...

  2. vue生命周期探究(一)

    前言 在使用vue开发的过程中,我们经常会接触到生命周期的问题.那么你知道,一个标准的工程项目中,会有多少个生命周期勾子吗?让我们来一起来盘点一下: 根组件实例:8个 (beforeCreate.cr ...

  3. [转]xshell使用技巧

    https://yq.aliyun.com/articles/44721 xshell是我用过的最好用的ssh客户端工具,没有之一.这个软件完全免费,简单易用,可以满足通过ssh管理linux vps ...

  4. HDU2449 Gauss Elimination 高斯消元 高精度 (C++ AC代码)

    原文链接https://www.cnblogs.com/zhouzhendong/p/HDU2449.html 题目传送门 - HDU2449 题意 高精度高斯消元. 输入 $n$ 个 $n$ 元方程 ...

  5. Python交互图表可视化Bokeh:3. 散点图

    散点图 ① 基本散点图绘制② 散点图颜色.大小设置方法③ 不同符号的散点图 1. 基本散点图绘制 import numpy as np import pandas as pd import matpl ...

  6. 016 pickle

    英文也是泡菜的意思. 学完了,还是感觉这个模块是蛮不错的,对多数据保存到文件中,然后在使用的时候,再读取出来,让程序闲的更加优雅,简洁. 一:介绍 1.为什么使用 在开篇已经介绍了,但是我这里粘贴一下 ...

  7. LoadRunner服务水平协议SLA

    服务水平协议 (或称 SLA)是以插入的事务为设置对象来为负载测试场景定义的具体目标. Analysis 将这些目标与 LoadRunner在运行过程中收集和存储的性能相关数据进行比较,然后确定目标的 ...

  8. 实验3 敏捷开发与XP实践实验报告

    一.实验报告封面 课程:Java程序设计 班级:1653班 姓名:高君天 学号:20165319 指导教师:娄嘉鹏 实验日期:2018年4月27日 实验时间:13:45 - 3:25 实验序号:实验三 ...

  9. Java实现Windows、Mouse监听器

    1.通过实现WindowListener接口来实现Windows监听器: import java.awt.event.WindowEvent; import java.awt.event.Window ...

  10. 上海市2019年公务员录用考试笔试合格人员笔试成绩(A类)

    考试类别:A类 注册编号 总成绩 注册编号 总成绩 注册编号 总成绩 注册编号 总成绩 4016574 127.4 5112479 145.9 5125732 124.3 5141074 159.9 ...