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 ...
随机推荐
- Android sdk 更新失败解决方发整理
解决办法: 设置本地hosts windows里hosts位置在C:\Windows\System32\drivers\etc,找到hosts文件 直接在hosts文件的最后加一行: 74.125.2 ...
- Redis源码阅读-sds字符串源码阅读
redis使用sds代替char *字符串, 其定义如下: typedef char *sds; struct sdshdr { unsigned int len; unsigned int free ...
- Spring读书笔记-----Spring核心机制:依赖注入
spring框架为我们提供了三种注入方式,分别是set注入,构造方法注入,接口注入.今天就和大家一起来学习一下 依赖注入的基本概念 依赖注入(Dependecy Injection),也称为IoC(I ...
- Zabbix二次开发_03api列表
基于zabbix 3.0 https://www.zabbix.com/documentation/3.0/manual/api/reference Method reference This sec ...
- Linux下tar解压缩命令
1.打包命令: 命令格式:tar -zcvf 压缩文件名.tar.gz 被压缩文件名 可先切换到当前目录下.压缩文件名和被压缩文件名都可加入路径. 2.解包命令: 命令格式:tar -zx ...
- jquery基础研究学习【效果】
---------------------------------分割线-------------------------------------- 2017年6月7日18:16:35Query 效果 ...
- Linux下apache安装php
php 1.下载解压 cd /usr/local/src wget http://mirrors.sohu.com/php/php-5.6.9.tar.gz tar zxvf php-5.6.9.ta ...
- Elasticsearch宕机问题
个人博客:https://blog.sharedata.info/ Elasticsearch 突然宕机,每次重启都只生成错误日志报错信息:## There is insufficient memor ...
- 使用3DES+Base64来加密传输iOS应用数据
本文转载至 http://www.erblah.com/post/objective-c/shi-yong-3des-base64lai-jia-mi-chuan-shu-iosying-yong-s ...
- lucas定理证明
Lucas 定理(证明) A.B是非负整数,p是质数.AB写成p进制:A=a[n]a[n-1]...a[0],B=b[n]b[n-1]...b[0]. 则组合数C(A,B)与C(a[n],b[n])* ...