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设计模式(十五)--备忘录模式
在Android中用于保存Activity状态的onSaveInstanceState()和恢复Activity状态的onRestoreInstanceState(), 这样的算不算是一种备忘录模式呢 ...
- Rserve方式连接别的服务器
Rserve Rserve的方式,这是一个基于TCP/IP的服务器,通过二进制协议传输数据,可以提供远程连接,使得客户端语言能够调用R 既然是TCP/IP 就可以在不同的机器上运行了 事实上官网给出了 ...
- java 性能检测工具 检测死锁等
死锁检测方法 1 JConsole 找到需要查看的进程,打开线程选项卡,点击检测死锁 2 jps查看java进程ID,使用jstack 7412输出信息 3 使用jvisualvm连接java虚拟机 ...
- 探究css中各种情况下的元素的垂直和水平居中的问题(面试题)
今天各种纠结,真的是不想写东西(ps 我比较懒)但是老是有人问这个问题,于是我就本着分享精神还是整理一下,好了废话不多说 开始上代码 问题:外边是一个容器,容器中还有一个容器,那么请问怎么让里边的容器 ...
- python 常用数据结构
#coding=utf- #元组,不可变序列(,) a=(,,,) print(a) a=tuple([,,,])#第二种定义方式 print(a) print(a[]) print(a[:]) #可 ...
- CSS3 --添加阴影(盒子阴影、文本阴影的使用)
CSS3 - 给div或者文字添加阴影(盒子阴影.文本阴影的使用)CSS3定义了两种阴影:盒子阴影和文本阴影.其中盒子阴影需要IE9及其更新版本,而文本阴影需要IE10及其更新版本.下面分别介绍两种 ...
- PHP-Manual的学习----【语言参考】----【类型】-----【对象】
Object 对象1.对象初始化要创建一个新的对象 object ,使用 new 语句实例化一个类: class foo{ function do_foo(){ echo &quo ...
- [学英语]vocabulary.com你都可以怎么用
vocabulary.com你都可以怎么用? 核心就是背单词. 1.利用纯英文环境熟悉单词,看看他们是如何解释单词的. 2.对于大段的文章,可以提炼出你需要背的单词. 3.以游戏的方式来背单词,app ...
- obj-c学习笔记
本文转载至 http://blog.csdn.net/c395565746c/article/details/7573793 当对象经过在dealloc方法处理时,该对象就已经处于已销毁状态,其它 ...
- iOS 多线程(队列、任务、串行、并行、同步、异步)