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 ...
 
随机推荐
- 洛谷P1339 热浪
			
P1339 热浪 529通过 1.3K提交 题目提供者yeszy 标签图论福建省历届夏令营 难度普及+/提高 提交该题 讨论 题解 记录 最新讨论 求助...为什么是未知错误… 求修正,貌似死循环 第 ...
 - HDU1859 最小长方形 (水
			
最小长方形 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submi ...
 - 【Foreign】染色 [LCT][线段树]
			
染色 Time Limit: 20 Sec Memory Limit: 256 MB Description Input Output Sample Input 13 0 1 0 2 1 11 1 ...
 - [BZOJ1040] [ZJOI2008]骑士 解题报告
			
Description Z国的骑士团是一个很有势力的组织,帮会中汇聚了来自各地的精英.他们劫富济贫,惩恶扬善,受到社会各界的赞扬.最近发生了一件可怕的事情,邪恶的Y国发动了一场针对Z国的侵略战争.战火 ...
 - [BZOJ1005]Prufer数列+排列组合
			
一棵树的Prufer数列 每次在剩下的树中找到标号最小的叶子节点(对于无根树而言即是度数为1的节点),删去. 同时将其父节点(即与其相连的唯一点)加入Prufer数列当中. 一个Prufer数列所对应 ...
 - php 中foreach比for快之原因
			
这里首先要谈到php 的hashtabletypedef struct _hashtable { uint nTableSize; // hash Bucket的大小,最小为8,以2x增长. uint ...
 - DotNETCore 学习笔记 宿主
			
Hosting -------------------------------------------------------------------------- Setting up a Host ...
 - bzoj 1067 特判
			
这道题的大题思路就是模拟 假设给定的年份是x,y,首先分为4个大的情况,分别是 x的信息已知,y的信息已知 x的信息已知,y的信息未知 x的信息未知,y的情况已知 x的信息未知,y的情况未知 然后对于 ...
 - stdafx.h、stdafx.cpp的作用
			
这两个文件用于建立一个预编译的头文件".PCH"和一个预定义的类型文件"STDAFX.OBJ".由于MFC体系结构非常大,各个源文件中都包含许多头文件,如果每次 ...
 - 【bzoj4094】【洛谷3097】Optimal Milking
			
假的,假的,都是假的. 题意是最大点独立集还要算贡献,写个网络流岂不是GG? 其实这个也就是奇偶不能选而已……所以无外乎这么四种情况: 左开右闭 左闭右开 都闭 都开 线段树按照套路维护一下就好了. ...