题目描述
某人刚学习了数位DP,他在某天忽然思考如下问题:
给定n,问有多少数对<x, y>满足:
x, y∈[1, n], x < y
x, y中出现的[0, 9]的数码种类相同
输入
一个整数n (n <= 107)
输出
输出一个数即答案
样例输入
30
样例输出
3
提示
<1, 11> <2, 22> <12, 21>
思路:
从1 到 n暴力枚举,结果加上 这个数之前已经出现过的相同数码的 数字个数 ,然后相同数字数码的个数加一;
用vis[] 存储 每类数字数码 的个数。
// vis[i], 将 i 转化为二进制数, 从左往右
// 那几位为 1, 则其 vis[i]的值这几种数码出现过的次数
// 例如 i = 3 = 0000000110
// vis[3] 就是 只出现1,2两种数码的 数字个数
最坏时间复杂度在我觉得在 5 * 10^7 左右,不过可以AC.
#include <iostream> #include <cstring> using namespace std; int vis[1<<11]; // vis[i], 将 i 转化为二进制数, 从左往右 // 那几位为 1, 则其 vis[i]的值这几种数码出现过的次数 // 例如 i = 3 = 0000000110 // vis[3] 就是 只出现1,2两种数码的个数 int main() { int n, temp, now; cin >> n; memset(vis, 0, sizeof(vis)); long long ans = 0; for(int i=1; i<=n; i++) { temp = i; now = 0; while(temp > 0) { now |= 1<<(temp%10); temp /= 10; } if(vis[now]) { // 如果 有小于 i 并且数码种类相同的只出现过 // 更新结果 ans += vis[now]; } // 更新 vis[] vis[now] ++; } cout << ans << endl;. return 0; }