Codeforces 914C Travelling Salesman and Special Numbers:数位dp
题目链接:http://codeforces.com/problemset/problem/914/C
题意:
对数字x进行一次操作,可以将数字x变为x在二进制下1的个数。
显然,一个正整数在进行了若干次操作后一定会变成1。
给定n,k(n用二进制表示给出,n <= 2^1000)。
问你有多少不超过n的正整数,将它们变为1所需的操作次数恰好为k。
题解:
由于n <= 2^1000,所以任何不超过n的数在进行了一次操作后,一定不超过1000。
所以先统计出1000以内所有数变成1所需的操作次数:f[i] = f[cal_bit(i)] + 1
那么最终答案 = ∑(恰好包含i个1,且不超过n的数字个数),其中f[i] == k-1。
所以接下来就要求恰好包含i个1,且不超过n的数字个数:
表示状态:
dp[i][j][0/1]表示已经填了前i位数,用了j个1,是否与n匹配(0/1),此时的方案数。
(n的最高位为第1位)
找出答案:
恰好包含i个1,且不超过n的数字个数 = dp[n][i][0] + dp[n][i][1]
如何转移:
对于dp[i][j][0]:
dp[i+1][j][0] += dp[i][j][0]
dp[i+1][j+1][0] += dp[i][j][0]
对于dp[i][j][1]:
如果n的第i+1位为1:
dp[i+1][j][0] += dp[i][j][1]
dp[i+1][j+1][1] += dp[i][j][1]
否则:
dp[i+1][j][1] += dp[i][j][1]
边界条件:
dp[1][0][0] = dp[1][1][1] = 1
最后统计下答案就好。
其中k==0或1的情况要特判。
AC Code:
#include <iostream>
#include <stdio.h>
#include <string.h>
#define MAX_N 1005
#define MOD 1000000007 using namespace std; int n,k;
int ans=;
int a[MAX_N];
int f[MAX_N];
int dp[MAX_N][MAX_N][];
string s; void read()
{
cin>>s>>k;
n=s.size();
for(int i=;i<n;i++) a[i+]=s[i]-'';
} int cal_bit(int x)
{
int cnt=;
int lowbit=x&-x;
while(lowbit)
{
cnt++;
x^=lowbit;
lowbit=x&-x;
}
return cnt;
} void cal_f()
{
f[]=;
for(int i=;i<=;i++)
{
f[i]=f[cal_bit(i)]+;
}
} void cal_dp()
{
memset(dp,,sizeof(dp));
dp[][][]=dp[][][]=;
for(int i=;i<n;i++)
{
for(int j=;j<=i;j++)
{
if(dp[i][j][])
{
dp[i+][j][]+=dp[i][j][];
dp[i+][j+][]+=dp[i][j][];
dp[i+][j][]%=MOD;
dp[i+][j+][]%=MOD;
}
if(dp[i][j][])
{
if(a[i+])
{
dp[i+][j][]+=dp[i][j][];
dp[i+][j+][]+=dp[i][j][];
dp[i+][j][]%=MOD;
dp[i+][j+][]%=MOD;
}
else
{
dp[i+][j][]+=dp[i][j][];
dp[i+][j][]%=MOD;
}
}
}
}
} void cal_ans()
{
for(int i=;i<=;i++)
{
if(f[i]==k-)
{
ans+=dp[n][i][]+dp[n][i][];
ans%=MOD;
}
}
} void work()
{
if(k==)
{
cout<<<<endl;
return;
}
cal_f();
cal_dp();
cal_ans();
if(k==) cout<<ans-<<endl;
else cout<<ans<<endl;
} int main()
{
read();
work();
}
Codeforces 914C Travelling Salesman and Special Numbers:数位dp的更多相关文章
- Codeforces 914C Travelling Salesman and Special Numbers (数位DP)
题意:题目中定义了一种运算,把数字x变成数字x的二进制位数.问小于n的恰好k次运算可以变成1的数的个数(题目中的n是二进制数,n最大到2^1000) 思路:容易发现,无论多么大的数,只要进行了一次运算 ...
- 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这种序列最大个 ...
- Travelling Salesman and Special Numbers CodeForces - 914C (数位dp)
大意: 对于一个数$x$, 每次操作可将$x$变为$x$二进制中1的个数 定义经过k次操作变为1的数为好数, 求$[1,n]$中有多少个好数 注意到n二进制位最大1000位, 经过一次操作后一定变为1 ...
- 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 pas ...
- 【Codecraft-18 and Codeforces Round #458 (Div. 1 + Div. 2, combined) C】 Travelling Salesman and Special Numbers
[链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 会发现. 进行一次操作过后. 得到的数字肯定是<=1000的 然后1000以下可以暴力做的. 则我们枚举第1步后得到的数字x是 ...
- Codeforces Beta Round #51 D. Beautiful numbers 数位dp
D. Beautiful numbers Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/55/p ...
- 2018 ACM 国际大学生程序设计竞赛上海大都会赛重现赛 J Beautiful Numbers (数位DP)
2018 ACM 国际大学生程序设计竞赛上海大都会赛重现赛 J Beautiful Numbers (数位DP) 链接:https://ac.nowcoder.com/acm/contest/163/ ...
- codeforces 55D - Beautiful numbers(数位DP+离散化)
D. Beautiful numbers time limit per test 4 seconds memory limit per test 256 megabytes input standar ...
随机推荐
- swift - 实现类似今日头条顶部标签和底部内容的动态解决方案
TYPageView TYPageView 类似今日头条 的标签导航解决方案,支持多种样式选择,基于swift3.0,支持文字颜色动态变化,底部选中线的动态变化 配图: 使用方法: let title ...
- JS中单引號/双引號以及外部js引入的一些问题
一.单引號和双引號的使用方法的问题 在JavaScript中能够使用单引號.双引號.二者也能够混合使用. 可是,身为菜鸟的我,却碰到了一些引號的使用问题. <body> <div s ...
- Warning: (3719, “‘utf8’ is currently an alias for the character set UTF8MB3, which will be replaced by UTF8MB4 in a future release. Please consider using UTF8MB4 in order to be unambiguous.”)
[1]本地版本 Mysql 8.0.12 创建表SQL: DROP TABLE IF EXISTS students; CREATE TABLE `students` ( `sId` ) UNSIGN ...
- 开源项目之easyrtmp
https://github.com/bigbluebutton86/EasyRTMP/tree/master/src http://dl.linux-sunxi.org/SDK/A20/A20_SD ...
- Coursera machine learning 第二周 quiz 答案 Octave/Matlab Tutorial
https://www.coursera.org/learn/machine-learning/exam/dbM1J/octave-matlab-tutorial Octave Tutorial 5 ...
- Linux下的目录操作
. 此层目录 .. 上层目录 - 前一个工作目录 ~ 当前用户的工作目录 ~account 表示account的家目录 1.cd:改变目录,change Directory的缩写. 2.pwd:显示当 ...
- Git客户端搭建环境(Windows系统)的使用
本文环境: 操作系统:Windows XP SP3 Git客户端:TortoiseGit-1.8.8.0-32bit 一.安装Git客户端 全部安装均采用默认! 1. 安装支撑软件 msysgit: ...
- Spring JDBC查询返回对象代码跟踪
在封装方法的时候突然发现通过 ResultSetMetaData的getColumnCount()获取到的列明会多一列(ROWSTAT),而且每次的值都是1,目前没有找到相关信息,在国外网站上看到有类 ...
- 解决iOS11 UIScrollView下移问题
iOS11 系统为UIScrollView增加一个contentInsetAdjustmentBehavior属性,默认为UIScrollViewContentInsetAdjustmentAutom ...
- git本地分支管理
查看分支:git branch创建分支:git branch dev重命名分支:git branch -m dev dev1删除分支:git branch -d dev切换分支:git checkou ...