number

题目描述

某人刚学习了数位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;
}


猜你喜欢

转载自blog.csdn.net/qq_38737992/article/details/80087201