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 ...
随机推荐
- 假的kd-tree小结
至今还不是很体会kd-tree这种东西,只不过体会了一种解决某些枚举问题的方法,就是当我们有一群元素,我们要到一个答案,答案在这些元素中的某个或某几个中,我们就会枚举他们,然而我们发现这样做十分低效, ...
- watch用法小记
By francis_hao Jun 30,2017 watch:周期性的执行一个一个程序,并全屏显示输出 概述 watch [options] command 描述 watch重复的运 ...
- Codeforces Round #510 (Div. 2) D. Petya and Array(树状数组)
D. Petya and Array 题目链接:https://codeforces.com/contest/1042/problem/D 题意: 给出n个数,问一共有多少个区间,满足区间和小于t. ...
- 通用adapter
http://blog.csdn.net/lmj623565791/article/details/38902805/
- HDU 多校对抗赛第二场 1004 Game
Game Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- c++编辑器下载地址
https://msdn.itellyou.cn/ 输入上述地址选中下图所示的按钮:
- NetTime
NetTime NetTime is a Simple Network Time Protocol (SNTP) client for Windows 95/98/Me/NT/2000/XP/Vist ...
- maven 压缩、合并 js, css
转载自:http://blog.csdn.net/fangxing80/article/details/17639607 我们知道在 Web 应用开发中为了提高客户端响应速度,需要将页面使用的资源最小 ...
- C# windows application Hello World
创建一个Windows application项目,然后可以调用里面的工具来生成代码. using System; using System.Collections.Generic; using Sy ...
- ios 全方位修改工程名
本文针对于彻底修改iOS工程名,不需要另外建工程,会整理的跟新工程完全一样 1. 选中旧工程名,改为新的 然后选择rename 2. 依次选择黄色文件夹,修改名字,千万不要在Xcode外修改!!! 修 ...