首页 > 其他分享 >U389139 至少有一位重复的数字-题解

U389139 至少有一位重复的数字-题解

时间:2024-09-22 16:34:47浏览次数:9  
标签:重复 题解 U389139 times int 枚举 res st

题目传送门

一、举例说明

以 \(654923\) 为例
要判断在 \([0, 654923]\) 区间至少有一位重复的数值的数,可以考虑其补集,即\(\color{red}所有位数均不重复的数\),用 \(N\) 减去补集即为结果。
首先可以将其分为两种情况。

  • 情况一,位数小于 \(6\) 位。所有位数均不重复的有 \(9 \times 9 \times 8 \times 7 \times 6\) 种(首位不为0)。
  • 情况二,位数等于 \(6\) 位,这也可以分为两种情况,首位小于 \(6\) 或等于 \(6\) 。对于首位小于 \(6\) 的数据,所有位数均不重复的有 \(5 \times 9 \times 8 \times 7 \times 6 \times 5\) 种情况。

对于首位等于 \(6\) ,那么就要考虑次高位。可以定义一个 \(st\) 数组,来记录是否有重复的数,比如 \(654423\) ,枚举到第四位也是 \(4\) ,那么后两位无论是多少数字都无意义了,都一定没有不重复的数。因此用该数组判断某一个数字是否已被使用,已被使用就直接跳过。
从第二位 \(j=5\) 开始枚举,于是我们第二位考虑比 \(j\) 小的数即 \(0\) 到 \(4\) ,加上后面四位不重复的数,即 \(8 \times 7 \times 6 \times 5 = P(8,4) = P(10-2,4)\),枚举后 \(st[5] = true\)。
从第三位 \(j=4\) 开始枚举,于是我们第三位考虑比 \(j\) 小的数即 \(0\) 到 \(3\) ,对于每一位数如果 \(st[k]\) 不为 \(true\) 的话,就说明此时这个数可以来当第三位数,加上后三位不重复的数即 \(7 \times 6 \times 5 = P(7,3) = P(10-3,3)\) ,枚举后 \(st[4] = true\) 。
以此将每一位数进行循环判定。每次循环完毕之后都判断一次,对应位数 \(j\) 是否重复有 \(st[j] = true\) ,如果重复了就不用继续往下面循环了,后面对应的数一定都重复。
最后跳出循环,同时我们在枚举的过程中,可以发现,第二位我们没有枚举 \(5\) ,第二位没有枚举 \(4\) …,第六位没有枚举 \(3\) ,如果能够枚举到这里,说明枚举过程中没有遇到重复的数,即这个数不是重复的数,所以要减去这个数。

二、代码实现

#include <bits/stdc++.h>
using namespace std;
int getSum(int a,int b){
    int res = 1;
    for(int i = a;b>0;b--,a--){
        res *= a;
    }
    return res;
}
vector<int>nums;
int numDupDigitsAtMostN(int n) {
    int res = n;
    //先将数整理为数组
    while(n) {
        nums.push_back(n % 10);
        n /= 10;
    }
    //情况一 比给定数位数少
    for(int i = nums.size() - 1;i > 0;i--){
        res -= 9 * getSum(9,i-1);
    }
    //情况二 和给定数位数相同 但最高位小于给定数最高位
    res -= (nums.back() - 1) * getSum(9,nums.size() - 1);
    //情况三 和给定数位数相同 最高位相同
    vector<bool> st(10);
    //然后去除首位的情况,设置首位为true不可再使用
    st[nums.back()] = true;
    for(int i = nums.size() - 2;i >= 0;i--){
        int j = nums[i];
        for(int k = 0;k < j;k++){
            //每次遇到前面用过的数就continue
            if(st[k]) continue;
            res -= getSum(10 - (nums.size() - i),i);
        }
        if(st[j]) {
            return res;
        }
        st[j] = true;
    }
    return res-1;
}
int main()
{
    int originNum;
    cin>>originNum ;
    cout<<numDupDigitsAtMostN(originNum);
    return 0;
}

如果你看到这里,你就浪费了2分钟,因为这代码太烦了(bushi

标签:重复,题解,U389139,times,int,枚举,res,st
From: https://www.cnblogs.com/StevenJiahao/p/18425484

相关文章

  • 【洛谷】P10417 [蓝桥杯 2023 国 A] 第 K 小的和 的题解
    【洛谷】P10417[蓝桥杯2023国A]第K小的和的题解题目传送门题解CSP-S1补全程序,致敬全A的答案,和神奇的预言家。写一下这篇的题解说不定能加CSP2024的RP代码#include<bits/stdc++.h>#definelowbit(x)x&(-x)#defineendl"\n"usingnamespacestd......
  • 【题解】【枚举】—— [NOIP2014 普及组] 比例简化
    【题解】【枚举】——[NOIP2014普及组]比例简化[NOIP2014普及组]比例简化题目背景题目描述输入格式输出格式输入输出样例输入#1输出#1提示1.思路解析2.AC代码[NOIP2014普及组]比例简化通往洛谷的传送门题目背景NOIP2014普及组T2题目描述在社交媒体......
  • 题解:AT_abc372_f [ABC372F] Teleporting Takahashi 2
    题意给出一个\(n\)个点的有向图,点\(i\)连向点\((i+1)\),点\(n\)连向点\(1\)。再给你\(m\)条额外边。你的初始位置为\(1\),问你移动\(k\)步的不同方案数(仅当路径不同时两个方案不同)。思路先想怎样暴力转移,显然移动\(k\)步到达一个点的方案数为所有跟这个点连边的移......
  • 题解:AT_abc372_e [ABC372E] K-th Largest Connected Components
    博客内食用更佳这道题的\(k\le10\)其实没什么用,代码区别仅在于手写平衡树和使用内置容器。这道题让查询与一个节点相连的所有点的信息,所以不难想到并查集。又因为让查询第\(k\)大,所以不难想到平衡树和线段树启发式合并。至此思路明显。我们对并查集中的每个节点开一个平......
  • 题解:AT_abc372_c [ABC372C] Count ABC Again
    博客内食用更佳乍一看好像是数据结构。我们结合题目所求内容考虑。对于每次修改,能对答案产生影响的最多只能是当前字符向前和向后延伸\(2\)个元素所构成的长为\(5\)的子串。那么我们先\(\mathcal{O}(n)\)计算出来初始答案。每次修改的时候,不妨先把\(i-2\simi\)和\(i-......
  • 第31次CCF-CSP认证考试 第一题 坐标变换(其一)满分题解
    第31次CCF-CSP认证考试第一题坐标变换(其一)写在前面的话这道题偏简单,我们废话不多说,直接上代码。老系统的链接:旧系统(不过只有第三十二次以及之前的,第三十三及以后的只能在新系统里提交查看分数)。代码#include<iostream>usingnamespacestd;intmain(){ intn,m; ......
  • 正方形计数 题解
    题意简述给出一个\(n\timesn\)的格点平面,有\(q\)次询问,求有多少正方形以\((x,y)\)为某一顶点,满足这个正方形顶点均在格点上,且边长为有理数。\(l\leq10^5\),\(q\leq5\times10^5\)。题目分析看到边长为有理数,想到「毕达哥拉斯三元组」("Pythagoreantriple",简称「......
  • CF 231 E Cactus 题解(仙人掌图上找环)
    codeforces提交记录题意有一个点仙人掌图(每个点都只属于至多一个简单环),给出kkk个询问,问点x......
  • 记一次ctf题解(rsa简单部分)
    一.ctfshow1.babyrsaimportgmpy2fromCrypto.Util.numberimport*e=65537p=104046835712664064779194734974271185635538927889880611929931939711001301561682270177931622974642789920918902563361293345434055764293612446888383912807143394009019803471816......
  • B4033 [语言月赛 202409] 考试 题解
    存下输赢代价,计算时先减为平局,判断输赢,如果还是输,那继续加一变为胜利这局,判断输赢。#include<bits/stdc++.h>usingnamespacestd;#definelllonglongconstintN=1e6+10;intn;inta[N];intb[N];intc[N];intmain(){ios::sync_with_stdio(false); cin>>n......