Codeforces 914 C Travelling Salesman and Special Numbers
Discription
The Travelling Salesman spends a lot of time travelling so he tends to get bored. To pass time, he likes to perform operations on numbers. One such operation is to take a positive integer x and reduce it to the number of bits set to 1 in the binary representation of x. For example for number 13 it's true that 1310 = 11012, so it has 3 bits set and 13 will be reduced to 3 in one operation.
He calls a number special if the minimum number of operations to reduce it to 1 is k.
He wants to find out how many special numbers exist which are not greater than n. Please help the Travelling Salesman, as he is about to reach his destination!
Since the answer can be large, output it modulo 109 + 7.
Input
The first line contains integer n (1 ≤ n < 21000).
The second line contains integer k (0 ≤ k ≤ 1000).
Note that n is given in its binary representation without any leading zeros.
Output
Output a single integer — the number of special numbers not greater than n, modulo 109 + 7.
Example
110
2
3
111111011
2
169
Note
In the first sample, the three special numbers are 3, 5 and 6. They get reduced to 2 in one operation (since there are two set bits in each of 3, 5 and 6) and then to 1 in one more operation (since there is only one set bit in 2).
最简单的数位dp类型,多加一维0\1表示是否贴上界(当初自己想的方法没想到还挺靠谱,,,基本上用了的题都对了)。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<vector>
#define ll long long
#define maxn 1010
#define ha 1000000007
using namespace std;
char s[maxn];
int n,m,c[maxn];
int num[maxn],k,ans;
int f[maxn][maxn][2];
//f[i][j][0/1]表示前i位中和为j,且是否贴上界的方案数 inline int add(int x,int y){
x+=y;
if(x>=ha) x-=ha;
return x;
} inline void init(){
num[0]=0;
for(int i=1;i<=1005;i++) num[i]=num[i^(i&-i)]+1;
c[1]=0,c[0]=123456;
for(int i=2;i<=1005;i++){
c[i]=c[num[i]]+1;
//c[i]<5,虽然可能并没有什么卵用
}
} inline void solve(){
n=strlen(s+1);
//一开始是贴上界的,因为之前的位都是0。
f[0][0][1]=1;
for(int i=1;i<=n;i++) if(s[i]=='1'){
//这一位是1的话是不可能选的数1个数为0且贴上界
f[i][0][0]=add(f[i-1][0][0],f[i-1][0][1]);
f[i][0][1]=0;
for(int j=1;j<=i;j++){
//不贴上界可能是 这一位为0且之前是否贴上界任意 或者 这一位为1且之前不贴上界
f[i][j][0]=add(add(f[i-1][j][0],f[i-1][j][1]),f[i-1][j-1][0]);
//贴上界只能是之前贴上界且当前位是1
f[i][j][1]=f[i-1][j-1][1];
}
}
else{
f[i][0][0]=f[i-1][0][0];
f[i][0][1]=f[i-1][0][1];
for(int j=1;j<=i;j++){
//不贴上界的话只能 这一位为0且之前不贴上界 或者 这一位为1且之前不贴上界
f[i][j][0]=add(f[i-1][j][0],f[i-1][j-1][0]);
//之所以没有f[i-1][j-1][1]是因为这一位是1的话是不可能贴上界的
f[i][j][1]=f[i-1][j][1];
}
} ans=0;
for(int i=0;i<=n;i++) if(c[i]==k-1) ans=add(ans,add(f[n][i][0],f[n][i][1])); //这样枚举<=n的数的1的个数会有一个漏洞,那就是1将会被算到k==1的里面去,所以要特判一下
if(k==0) ans++;
else if(k==1) ans--;
} int main(){
init();
scanf("%s",s+1);
scanf("%d",&k);
solve();
printf("%d\n",ans);
return 0;
}
Codeforces 914 C Travelling Salesman and Special Numbers的更多相关文章
- Codeforces 914 C. Travelling Salesman and Special Numbers (数位DP)
题目链接:Travelling Salesman and Special Numbers 题意: 给出一个二进制数n,每次操作可以将这个数变为其二进制数位上所有1的和(3->2 ; 7-> ...
- Codeforces 374 C. Travelling Salesman and Special Numbers (dfs、记忆化搜索)
题目链接:Travelling Salesman and Special Numbers 题意: 给了一个n×m的图,图里面有'N','I','M','A'四种字符.问图中能构成NIMA这种序列最大个 ...
- Codeforces 914C Travelling Salesman and Special Numbers:数位dp
题目链接:http://codeforces.com/problemset/problem/914/C 题意: 对数字x进行一次操作,可以将数字x变为x在二进制下1的个数. 显然,一个正整数在进行了若 ...
- Travelling Salesman and Special Numbers CodeForces - 914C (数位dp)
大意: 对于一个数$x$, 每次操作可将$x$变为$x$二进制中1的个数 定义经过k次操作变为1的数为好数, 求$[1,n]$中有多少个好数 注意到n二进制位最大1000位, 经过一次操作后一定变为1 ...
- Codeforces 914C Travelling Salesman and Special Numbers (数位DP)
题意:题目中定义了一种运算,把数字x变成数字x的二进制位数.问小于n的恰好k次运算可以变成1的数的个数(题目中的n是二进制数,n最大到2^1000) 思路:容易发现,无论多么大的数,只要进行了一次运算 ...
- 【Codecraft-18 and Codeforces Round #458 (Div. 1 + Div. 2, combined) C】 Travelling Salesman and Special Numbers
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 会发现. 进行一次操作过后. 得到的数字肯定是<=1000的 然后1000以下可以暴力做的. 则我们枚举第1步后得到的数字x是 ...
- HDU 5402(Travelling Salesman Problem-构造矩阵对角最长不相交路径)
Travelling Salesman Problem Time Limit: 3000/1500 MS (Java/Others) Memory Limit: 65536/65536 K (J ...
- HDU 5402 Travelling Salesman Problem (构造)(好题)
大致题意:n*m的非负数矩阵,从(1,1) 仅仅能向四面走,一直走到(n,m)为终点.路径的权就是数的和.输出一条权值最大的路径方案 思路:因为这是非负数,要是有负数就是神题了,要是n,m中有一个是奇 ...
- HDOJ 5402 Travelling Salesman Problem 模拟
行数或列数为奇数就能够所有走完. 行数和列数都是偶数,能够选择空出一个(x+y)为奇数的点. 假设要空出一个(x+y)为偶数的点,则必须空出其它(x+y)为奇数的点 Travelling Salesm ...
随机推荐
- 栈与递归的实现(Hanoi塔问题等等)
函数中有直接或间接地调用自身函数的语句,这样的函数称为递归函数.递归函数用 得好,可简化编程工作.但函数自己调用自己,有可能造成死循环.为了避免死循环,要 做到两点: (1) 降阶.递归函数虽然调用自 ...
- 常见通用的 JOIN 查询
SQL执行循序: 手写: SELECT DISTINCT <query_list> FROM <left_table> <join type> JOIN <r ...
- Spring学习-- IOC 容器中 bean 的生命周期
Spring IOC 容器可以管理 bean 的生命周期 , Spring 允许在 bean 声明周期的特定点执行定制的任务. Spring IOC 容器对 bean 的生命周期进行管理的过程: 通过 ...
- eclipse怎样快速的给代码段添加try catch
打开要进行异常处理的java代码页面. 选中要添加try..catch的代码段,然后点击鼠标右键,选择[Sourround With]选项. 然后选择[Try/Catch Block]或者[6 try ...
- Nios II 中的缓存和内存数据的读写
nios 使用地址中31bit来表示访问是否bypass cache.如果bit 31=0 表示不bypass cache,即使用cache里的数据:如果bit 31=1表示bypass cache, ...
- Chocolatey 使用
最近空了下来不干点什么就感觉脑袋热,可是出过的问题挖过的坑还是要自己去解决. 一直网络不好安装choco一直都是报错,今天又建立了chocolatey 在windows上来用,网络问题解决了,类似于m ...
- elasticsearch.helpers.ScanError: Scroll request has only succeeded on xx shards
# 当index=''为空时出现此错误
- mysql六:索引原理与慢查询优化
一 介绍 为何要有索引? 一般的应用系统,读写比例在10:1左右,而且插入操作和一般的更新操作很少出现性能问题,在生产环境中,我们遇到最多的,也是最容易出问题的,还是一些复杂的查询操作,因此对查询语句 ...
- Execute a terminal command from a Cocoa app
http://stackoverflow.com/questions/412562/execute-a-terminal-command-from-a-cocoa-app in the spirit ...
- 原型 Boolean String Math Date知识点
原型 1.定义 每一个对象都有原型 原型仍然是一个对象 模拟实现面向对象的继承性 2.原型链 对象的原型还有原型 对象除了可以使用自有属性还可以继承原型上的属性 3.获取原型 对象.__proto__ ...