F. Igor and Interesting Numbers
http://codeforces.com/contest/747/problem/F
cf #387 div2 problem f
非常好的一道题。看完题,然后就不知道怎么做,感觉是dp,但是不知道怎么枚举。还有就是一般求第k小的思路一般是什么?对这类题目理解的不是很好。
这道题,跟上一篇的题解里面写的hdu 1002 递增数的题目的解法差不多,但是底层的求解需要花一些时间去推敲!
不会做,就看官方题解,看不懂说的什么。就从下面的讨论找大神的题解。
I can describe my solution
Binary search on what is the answer(mi). So, the problem reduces to counting number of numbers <= mi such that each digit occurs <= t times.
In fact, we solve a more general problem — find number of numbers of length i such that each digit j occurs <= b[j] times. 0 complicates the matter somewhat but for the time assume that 0 can be placed anywhere and obeys constraint like the normal digits. Then formulate dp[i][j] = number of numbers with i digits and place only digits <= j. Iterate k = how many j digits will be there — 0 to min(i,b[j]) then dp[i][j] = sum((i choose k)*dp[i-k][j-1]). Base cases are simple to write.
Overall count can be calculated by fixing highest digit(depends on mi) and then a dp call, then next digits etc.. similar to what we do in offline digits dp solution. The prefix digits that are fixed decide what array b is(t — number of times digit has occurred till now).
Finally for 0, simply calculate for lesser lengths using a similar logic. Checkout my solution for more details.
Time complexity = O(p^3*d^3) where p=max digits in answer=9 and d=16 and = runs in 15 ms :)
看完这个之后,思路就清晰很多了,然后接下来就是二分的判断条件,对于给定mi,如何判断比它小的满足要求的数的个数呢? 这个求解思路跟上面写的hdu的1002思路一致, 按长度进行累加和, 因为一个数的长度很小,这里int的16进制表示,最大长度为32/4 = 8, 这个长度很短, 可以通过预处理来快速求解。所以,首先需要解决,长度为k的满足要求的数的个数这个问题!由于题目要求的是每个数出现次数小于等于t, 所以如果按位枚举的话,需要记住每一个数的出现次数,这个好像不容易解决,然后考虑可以使用的数的最大值,使用排列组合的方式,就是上面的思路进行解决。这个问题解决之后, 然后就是对于一个数,先求长度比它小的数的个数,然后求解跟他长度一致的数的个数,依次从高位到低位, 进行求解,枚举每一个数字的方式进行。讲的好乱,我都听不懂了!
注意上面的复杂度分析:代码运行速度非常快。
又掌握一种套路,就是上面的dp求解的过程,这个不好思考,求解每个数字出现此小于等于t的数字的个数,使用组合的方式,注意对0的单独处理。
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <string.h>
#include <fstream>
#include <cassert>
using namespace std; #define boost ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0)
#define sz(a) int((a).size())
#define rep(i, s, n) for(int i = s; i <= (n); ++i)
#define rev(i, n, s) for(int i = (n); i >= s; --i)
#define fore(x, a) for(auto &&x : a)
typedef long long ll;
const int mod = ;
const int N = ; int a[];
int t;
int b[];
ll dp[][];
ll c[][]; ll go(int p, int x) {
if (p == -) return ;
if (x == ) {
if (t - b[x] >= p + ) return ;
return ;
}
ll &res = dp[p][x];
if (res >= ) return res;
res = ;
rep(i, , min(p + ,t-b[x])) {
res += c[p+][i]*go(p - i, x - );
}
return res;
} char hex(int x) {
if (x >= ) return 'a' + (x - );
return '' + x;
} ll g[]; ll f(int x) {
ll res = ;
memset(b, , sizeof(b));
rep(i, , ) {
memset(dp, -, sizeof(dp));
b[i]++;
res += go(x - , );
b[i]--;
}
return res;
} int main() {
#ifdef loc
if (!freopen((string(FOLDER) + "inp.txt").c_str(), "r", stdin)) {
assert();
}
freopen((string(FOLDER) + "out.txt").c_str(), "w", stdout);
#endif
boost;
ll k;
cin >> k >> t;
rep(i, , ) {
c[i][] = ;
rep(j, , i) {
c[i][j] = c[i - ][j] + c[i - ][j - ];
}
}
rep(i, , ) {
g[i] = f(i);
if (i > ) g[i] += g[i - ];
}
ll lo = , hi = (1LL << ) - ;
while (lo < hi) {
ll mi = (lo + hi) / ;
ll p = mi + ;
int td = ;
rep(i, , ) {
a[i] = p % ;
p /= ;
td = i;
if (p == ) {
break;
}
}
ll tot = td > ? g[td - ] : ;
memset(b, , sizeof(b));
rev(i, td, ) {
rep(j,(i==td)?:, a[i] - ) {
b[j]++;
if (b[j] <= t) {
memset(dp, -, sizeof(dp));
tot += go(i - , );
}
b[j]--;
}
b[a[i]]++;
if (b[a[i]] > t) break;
}
if (tot >= k) hi = mi;
else lo = mi + ;
}
vector<int> ans;
while (lo > ) {
ans.push_back(lo % );
lo /= ;
}
reverse(ans.begin(), ans.end());
fore(x, ans) {
cout << hex(x);
}
cout << endl;
return ;
}
F. Igor and Interesting Numbers的更多相关文章
- CF747F Igor and Interesting Numbers
我佛了,这CF居然没有官方题解. 题意:给定k,t,求第k小的16进制数,满足每个数码的出现次数不超过t. 解: 每个数都有个出现次数限制,搞不倒.一开始想到了排序hash数位DP,不过写了写觉得不胜 ...
- Codeforces 747F Igor and Interesting Numbers DP 组合数
题意:给你一个数n和t,问字母出现次数不超过t,第n小的16进制数是多少. 思路:容易联想到数位DP, 然而并不是...我们需要知道有多少位,在知道有多少位之后,用试填法找出答案.我们设dp[i][j ...
- ural 2070. Interesting Numbers
2070. Interesting Numbers Time limit: 2.0 secondMemory limit: 64 MB Nikolay and Asya investigate int ...
- 算法笔记_093:蓝桥杯练习 Problem S4: Interesting Numbers 加强版(Java)
目录 1 问题描述 2 解决方案 1 问题描述 Problem Description We call a number interesting, if and only if: 1. Its d ...
- java实现 蓝桥杯 算法提高 Problem S4: Interesting Numbers 加强版
1 问题描述 Problem Description We call a number interesting, if and only if: 1. Its digits consists of o ...
- F Find the AFei Numbers
链接:https://ac.nowcoder.com/acm/contest/338/F来源:牛客网 题目描述 AFei loves numbers. He defines the natural n ...
- CSU 2018年12月月赛 F(2218): Finding prime numbers
Description xrdog has a number set. There are 95 numbers in this set. They all have something in com ...
- URAL 2070 Interesting Numbers (找规律)
题意:在[L, R]之间求:x是个素数,因子个数是素数,同时满足两个条件,或者同时不满足两个条件的数的个数. 析:很明显所有的素数,因数都是2,是素数,所以我们只要算不是素数但因子是素数的数目就好,然 ...
- 【线性筛】【筛法求素数】【约数个数定理】URAL - 2070 - Interesting Numbers
素数必然符合题意. 对于合数,如若它是某个素数x的k次方(k为某个素数y减去1),一定不符合题意.只需找出这些数. 由约数个数定理,其他合数一定符合题意. 就从小到大枚举素数,然后把它的素数-1次方都 ...
随机推荐
- cocos2d-x jsbinding 在线更新策略设计
在线更新是用脚本编写游戏逻辑的特有功能,由于脚本语言是边解释边编译的特性,使得游戏在运行的时候可以通过下载最新的脚本来执行游戏逻辑.在不修改Native接口的情况下,在线更新每次更新只需要下载一个(5 ...
- java实现迷宫算法--转
沿着所有方向进行探测,有路径则走,没有路径则从栈中回退. 回溯法是一种不断试探且及时纠正错误的搜索方法,下面的求解过程采用回溯法.从入口出发,按某一方向向前探索,若能走通(未走过的),即某处可以到达, ...
- fs/ext2/inode.c相关函数注释
用数组chain[4]描述四种不同的索引,即直接索引.一级间接索引.二级间接索引.三级间接索引.举例说明这个结构各个域的含义.如果文件内的块号为8,则不需要间接索引,所以只用chain[0]一个Ind ...
- vsftpd虚拟用户创建实例(转载)
vsftpd虚拟用户创建实例 发布:theboy 来源:net [大 中 小] vsftpd虚拟用户创建实例,有需要的朋友可以参考下. vsftpd虚拟用户创建实例,有需要的朋友可以参考 ...
- 关于解决[INSTALL_FAILED_UPDATE_INCOMPATIBLE]
通过adb install安装apk,报错Failure [INSTALL_FAILED_UPDATE_INCOMPATIBLE]. 说明没有正常卸载原apk,基本都是直接通过rm XXX.apk所造 ...
- Foundation学习笔记
. 链接:Foundation学习,代码实例总结(pdf版) .
- 1.4.2 solr字段类型--(1.4.2.5)使用枚举字段
1.4.2 solr字段类型 (1.4.2.1) 字段类型定义和字段类型属性. (1.4.2.2) solr附带的字段类型 (1.4.2.3) 使用货币和汇率 (1.4.2.4) 使用Dates(日期 ...
- Java中ThreadLocal的设计与使用
早在Java 1.2推出之时,Java平台中就引入了一个新的支持:java.lang.ThreadLocal,给我们在编写多线程程序时提供了一种新的选择.使用这个工具类可以很简洁地编写出优美的多线程程 ...
- PHP trim()函数的一些用法
string trim ( string $str [, string $charlist ] ) - 去除字符串首尾处的空白字符(或者其他字符) trim()函数当第二个参数为空时,默认去掉空格.制 ...
- 基本API-StdIn.java
/************************************************************************* * Compilation: javac StdI ...