Travelling Salesman and Special Numbers
prologue
模拟赛的一道题,结果没做出来,丢大人,败大兴。所以过来糊一篇题解。
analysis
我们看到数据范围这么大,那么肯定不可以一个一个遍历(废话),所以就要考虑这个题目的性质。
我们先假设,极端数据 \(2 ^ {1000} - 1\),这个数字中包含了 \(999\) 个 1(正好感冒了能不能让我喝了)。下一次的数据就是 \(999\),这个时候,\(999\) 的二进制表示为 \(11 1110 0111\),下次就是 \(8\),再下次就是 \(1\) 了。这个时候的最少变换次数是 \(3\)。
我们看到这个数据缩小是很快的。那我们再进一步研究观察。
由于上限原因,所以我们第一次变换之后的数字一定为 \(\le 1000\) 的数字。我们又知道(不知道的掏计算器) \(2 ^ {10} = 1024\) 已经大于 1000 了,为了方便统计,适当放大数据。下次需要进行操作的数字就变成了 $ [0, 10] $ 就更小了,这个时候手搓一下,发现 \(7\) 这个数据是 \([0, 10]\) 之间的二进制表示下包含 1 最多的一个数字。
我们就求出来了这个恰好变换次数的上限。对于 100% 的数据而言,一定有:
- \(2 \le k \le 5\) 有解。
- \(k > 5\) 无解。
这个时候特判两个情况:
- \(k = 1\) 时,答案的个数为 \(length_s - 1\)。
- \(k = 0\) 时,答案为 1(只有 1 这种情况)。
我们之后就去考虑怎么计算这个值。
我们可以考虑一种类似于数位 dp 的思想,从高位往低位,用 \(f[i][j]\) 表示已经填了 i 个 1,剩下 j 位随便填,并且恰好 k 次变换之后能够变成 1 的方案数。
考虑递推式,从定义出发,预处理出来可能的值:
\]
\]
计算方案数量:
\]
注意,如果我们最后的这个数字符合我们的最后变换数量少一,就是最后可以变到 1,我们要给方案数加 1。
code time
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define rl register ll
#define endl '\n'
const ll N = 1010, P = 1e9 + 7;
char ch[N];
ll n, m, g[N], f[N][N];
int main()
{
scanf("%s%lld", ch, &m);
n = strlen(ch);
if(m == 0) puts("1");
else if(m == 1) cout << n - 1 << endl;
else if(m > 5) cout << "0" << endl;
else
{
for(rl i=2; i <= 1000; ++ i)
{
ll cnt = 0;
for(rl j=i; j; j >>= 1)
if(j & 1) cnt ++;
g[i] = g[cnt] + 1;
}
for(rl i=1; i <= n; ++ i) f[0][i] = g[i] == m - 1;
for(rl i=1; i <= n; ++ i)
for(rl j=0; j <= n; ++ j)
{
f[i][j] = f[i - 1][j];
if(j + 1 <= n) f[i][j] = (f[i][j] + f[i-1][j + 1]) % P;
}
ll res = 0, t = 0;
for(rl i=0; i < n; ++ i)
if(ch[i] == '1')
{
res = (res + f[n - i - 1][t]) % P; t ++ ;
}
if(g[t] == m - 1) cout << res + 1 << endl;
else cout << res << endl;
}
return 0;
}
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 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 ...
- 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) 思路:容易发现,无论多么大的数,只要进行了一次运算 ...
- Codeforces 914C Travelling Salesman and Special Numbers:数位dp
题目链接:http://codeforces.com/problemset/problem/914/C 题意: 对数字x进行一次操作,可以将数字x变为x在二进制下1的个数. 显然,一个正整数在进行了若 ...
- 【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 ...
随机推荐
- 学习websocket,原来这么简单
简单介绍 websocket WebSocket是一种在TCP连接上进行全双工通信的协议. WebSocket通信协议于2011年被IETF定为标准. 然后WebSocket API也被W3C定为标准 ...
- 使用Python接口自动化测试post请求和get请求,获取请求返回值
引言我们在做python接口自动化测试时,接口的请求方法有get,post等:get和post请求传参,和获取接口响应数据的方法: 请求接口为Post时,传参方法我们在使用python中request ...
- EaselJS 源码分析系列--第三篇
这一篇分析另外四个稍显高级的显示类 -- Sprite.Movieclip.DOMElement.BitmapText SpriteSheet SpriteSheet 比较简单 它继承自 EventD ...
- 原生poi实现模版导出
背景 我们公司是内网开发,外网jar包我的权限不够,所以easyexcel jar包无法使用,参考了easyexcel的填充思想,写了一个较简单的填充方法,如果直接用easyexcel的话,可以参考这 ...
- 2.融合进阶:Stacking与Blending
1 堆叠法Stacking 1.1 堆叠法的基本思想 堆叠法Stacking是近年来模型融合领域最为热门的方法,它不仅是竞赛冠军队最常采用的融合方法之一,也是工业中实际落地人工智能时会考虑的方案之一. ...
- Java List集合根据某字段去重
去重方法 单个字段为条件去重 /** * 单字段去重 * @param jackpotList1 新集合 * @param jackpotList 需要去重的集合 * @return */ priva ...
- Prometheus-5:relabel标签重新打标
Prometheus relabel重新打标 对target重新打标是在数据抓取之前动态重写target标签的强大工具,在每个数据抓取配置中,可以定义多个relabel步骤,它们将按照定义的顺序依次执 ...
- Vue笔记(一)
1. Vue.js是什么? 1). 一位华裔前Google工程师(尤雨溪)开发的前端js库 2). 作用: 动态构建用户界面 3). 特点: * 遵循MVVM模式 * 编码简洁, 体积小, 运行效率高 ...
- ubuntu下安装mysqlclient报错
输入以下代码: 1 解决方法: 2 sudo apt-get install libmysqlclient-dev 3 4 再次安装: 5 pip3 install mysqlclient 文章链接: ...
- 是时候丢掉BeanUtils了
前言 为了更好的进行开发和维护,我们都会对程序进行分层设计,例如常见的三层,四层,每层各司其职,相互配合.也随着分层,出现了VO,BO,PO,DTO,每层都会处理自己的数据对象,然后向上传递,这就避免 ...