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 ...
随机推荐
- Codeforces Round #351 (VK Cup 2016 Round 3, Div. 2 Edition) C (用map 超时)
C. Bear and Colors time limit per test 2 seconds memory limit per test 256 megabytes input standard ...
- 使用google api material icons在网页中插入图标
在<head></head>中加入这一句: <link rel='stylesheet' href='http://fonts.googleapis.com/icon?f ...
- Install the Active Directory Administration Tools on Windows Server
安装 Active Directory 管理工具 To manage your directory from an EC2 Windows instance, you need to install ...
- SQLyog 使用笔记,自增主键数据冲突错误
select max(id) from test ; desc test ; insert into test (a,b,c) values ('abc','123-213','test'); RE ...
- oracle12c创建用户等问题
一:前言 这几天我重新装了下电脑,然后自己有试着去装了下oracle11g,结果还是失败了然后我自己又去下载了最新的oracle12c,oracle12c中有两个用户sys和system,scott已 ...
- 最大流算法 ISAP 模板 和 Dinic模板
ISAP // UVa11248 Frequency Hopping:使用ISAP算法,加优化 // Rujia Liu struct Edge { int from, to, cap, flow; ...
- mysql5.7.11安装遇到的问题
首次安装mysql5.7.11绿色版,真是破费功夫,现记录安装中遇到的问题,只是解决了问题,而不清楚问题的由来. 问题一: 问题二: 问题三: 问题四: 我的my.ini配置文件: [mysql] # ...
- 【转载】字符串最小表示法-O(n)算法
原博客链接:http://blog.csdn.net/zy691357966/article/details/39854359 未授权,侵权删. 因为这篇博客写得真好..转载了.. 红色的字是原博主写 ...
- HDU 4334 Trouble (数组合并)
Trouble Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Su ...
- Splunk Power User认证
课程介绍 | 通过 Splunk Fundamentals Part 1 课程考试 | 获取splunk certificate user 证书 | 课程为14节课+课后实验环境+课后习题 | 课程有 ...