首页 > 其他分享 >P10404 「XSOI-R1」原神数 题解

P10404 「XSOI-R1」原神数 题解

时间:2024-08-23 16:49:19浏览次数:5  
标签:判断 阈值 int 题解 sqrt XSOI 原神数 binom

一篇题解需要一张头图。

容易发现超过十位的数都不是原神数,因为只有十个数字,不可能保证十一个位置互不相同。
同时恰好十位的数也不可能是原神数,因为数位互不相同的十位数的数位和为 \(45\),被 \(3\) 整除,一定是 \(3\) 的倍数。
于是把原神数的范围缩小到 \([1, 10^9)\)。

显然不能在回答询问时处理答案,考虑预处理出所有原神数并二分回答询问。

考虑先满足数位互不相同的限制,DFS 搜索出所有数位互不相同的数并判断其是否是质数。
可以计算出,需要判断 \(\binom 9 8 1! + \binom 9 7 2! + \binom 9 6 3! + \cdots + \binom 9 9 9! = 986409\) 次。
只需要寻找一个快速的质数判断方法,回收头图:Miller–Rabin 被卡得飞起。
考虑分治:使用线性筛判断不超过阈值的数,超过阈值的数通过枚举线性筛得到的素数进行判断。
取阈值为 \(2 \cdot 10^6\) 可以通过本题。

正确性证明 定理:对于一个合数 \(x\),其最小质因子不超过 \(\sqrt x\)。在 \([2, 2 \cdot 10^6)\) 的素数内一定可以找到待判断的数(如果是合数)的最小质因子。正确性得证。

时间复杂度证明 设待判断的数为 \(x\),阈值为 \(B\)。如果 \(x \leqslant B\),可以 \(O(1)\) 判断;如果 \(x > B\),根据前述定理,会枚举 \(\pi(\lfloor \sqrt x \rfloor) \sim \frac {\sqrt x} {\ln(\sqrt x)}\) 个质数。勉强可以通过。

因为有些卡常所以比较难看的代码。

#include <algorithm>
#include <iostream>
#include <vector>

typedef long long ll;

using namespace std;

const int lim = 2e6;

int q;
ll l, r;
bool isp[lim + 5];
int pr[lim + 5], pi;
static inline bool chk(int x) {
    if (x <= lim)
        return !isp[x];
    for (int i = 1; pr[i] * pr[i] <= x; ++i)
        if (x % pr[i] == 0)
            return false;
    return true;
}

bool vis[12];
vector<int> gen;
static inline void dfs(int u, int val, int aim) {
    if (u == aim) {
        if (chk(val))
            gen.push_back(val);
        return;
    }
    for (int i = 0; i <= 9; ++i) {
        if (u == 0 && i == 0)
            continue;
        if (vis[i])
            continue;
        vis[i] = 1;
        dfs(u + 1, val * 10 + i, aim);
        vis[i] = 0;
    }
}

signed main() {
#ifndef ONLINE_JUDGE
    freopen("1.in", "r", stdin);
#endif
    isp[0] = isp[1] = 1;
    for (int i = 2; i <= lim; ++i) {
        if (!isp[i])
            pr[++pi] = i;
        for (int j = 1; j <= pi && i * pr[j] <= lim; ++j) {
            isp[i * pr[j]] = 1;
            if (i % pr[j] == 0)
                break;
        }
    }
    for (int i = 1; i <= 9; ++i)
        dfs(0, 0, i);
    scanf("%d", &q);
    while (q--) {
        scanf("%lld %lld", &l, &r);
        printf("%d\n", (int)(upper_bound(gen.begin(), gen.end(), r) - lower_bound(gen.begin(), gen.end(), l)));
    }
    return 0;
}

标签:判断,阈值,int,题解,sqrt,XSOI,原神数,binom
From: https://www.cnblogs.com/bluewindde/p/18376399

相关文章

  • P10528 [XJTUPC2024] 崩坏:星穹铁道 题解
    求方案数,分多种情况,不难想到DP。设\(dp_{i,j}\)表示已经行动\(i\)次,剩余战技点个数为\(j\)的方案数,容易得到以下转移方程。\(a_i=1\)时,有\[dp_{i,j}=\begin{cases}0,&j=0,\\dp_{i-1,j-1},&1\leqslantj\leqslant4,\\dp_{i-1,j-1}+dp_{i......
  • LGP10702 [SNCPC2024] 下棋题解
    P10702[SNCPC2024]下棋本蒟蒻的第一篇题解定位博弈论(nim)+进制转换相关知识OIWIKI博弈论NIM进制转换正题读题所有k进制下所有数位的乘积为自身因子的数。他称之为LNC数。给出x枚棋子,然后LNC选定一个整数k(k≥2)。随后他们交替取走若干枚棋子,要求取走的棋......
  • 【题解】Solution Set - NOIP2024集训Day14 CDQ分治
    【题解】SolutionSet-NOIP2024集训Day14CDQ分治https://www.becoder.com.cn/contest/5482「CF364E」EmptyRectangles*3000摆烂了。「SDOI2011」拦截导弹CDQ的例题,之前做过(现在试图自己再做出来。第二问只用在第一问里面记录每一次是从哪个\(j\)​转移过来的,以及......
  • P10559 [ICPC2024 Xi'an I] The Last Cumulonimbus Cloud 题解
    这种题有一个常见的根号分治做法:设\(d\)为度数,显然有\(O(1)\)修改单点,\(O(d)\)查询邻域和\(O(d)\)修改邻域,\(O(1)\)查询单点两种暴力。对度数大于\(\sqrtn\)的点使用前者,度数小于等于\(\sqrtn\)的点使用后者,可以做到\(O(m\sqrtn)\)的时间复杂度。这种做法的本......
  • CF1575G GCD Festival 题解
    考虑欧拉反演\[\sum\limits_{d\midn}\varphi(d)=n\]则原式可以化为\[\begin{align*}&\sum\limits_{i=1}^n\sum\limits_{j=1}^n\gcd(a_i,a_j)\cdot\gcd(i,j)\\=&\sum\limits_{i=1}^n\sum\limits_{j=1}^n\gcd(a_i,a_j)\sum\li......
  • CF163E e-Government 题解
    题目传送门前置知识AC自动机|树状数组解法一次性将所有模式串加入AC自动机,然后处理加入和删除,考虑单次操作对答案的贡献。因为模式串\(T\)在文本串\(S\)中出现的次数之和等价于\(T\)在\(S\)的所有前缀中作为后缀出现的次数之和。这就很和\(fail\)树上跳到根节......
  • [题解] permutation
    [题解]Permutation解析一眼DP或者组合。70pts场上推的DP对于\((4,2,2)\),先把所有序列枚举出来:\[\begin{split}1\\\2\\1\\\3\\1\\\4\\--\\2\\\3\\2\\\4\\3\\\4\end{split}\]可以发现,对于分割线上的部分,可以看作\((3,1,1)\)的所有序列......
  • csp模拟27-金箱子(题解)
    题目链接(显然还没有找到原题)虽说我现在才学会期望dp显得不太好,但没办法,谁让我比较菜~~,之前模拟赛已经考过几道类似的题了,但都一笔带过了,这次算是正式学习了一下这类题,于是就有了这篇题解。首先看到k次方首先想到的就是我们在进行dp转移的时候不太方便,这个时候很自然的想到二项......
  • 题解:P9041 [PA2021] Fiolki 2
    \(\text{Link}\)题意给定一个\(n\)个点\(m\)条边的DAG,定义\(f(l,r)\)表示最多选取多少条不相交路径\((s_i,t_i)\)满足\(s_i\in[1,k],t_i\in[l,r]\),其中不能有任意一点同时在两条选出的路径上。对\(\forallx\in[0,k)\)求出有多少\([l,r]\sube(k,n]\)使得\(f(l,r)......
  • 题解:P10881「KDOI-07」能量场
    \(\text{Link}\)题意给你一个长为\(n\)的序列\(a_{1\dotsn}\),定义一条边\((u,v)\)的权值为\(a_u+a_v\)。对于一张图,定义其权值为包含的所有边的权值乘积。求所有\(n\)个点的有标号基环树的权值之和。对\(998244353\)取模。\(n\le10^3\)。思路非常厉害的题,zky倾......