BZOJ 2186 [SDOI 2008]沙拉公主的困惑 简单数论
2018-02-23 20:40
369 查看
传送门
思路
参考代码
传送门
思路
要完成这个题,首先要知道这么一个结论:若 gcd(a,b)=1gcd(a,b)=1,则 gcd(a,b+a)=1gcd(a,b+a)=1。结合辗转相除法的证明过程,这个结论显然。因此,题目中要求的东西为:
φ(m!)n!m!φ(m!)n!m!
展开得:
=m!(∏ipi−1pi)n!m!=n!(∏ipi−1pi)=m!(∏ipi−1pi)n!m!=n!(∏ipi−1pi)
其中pipi 表示 m!m! 的质因子。
n!n! 的阶乘可以 O(n)O(n) 预处理,后半部分需要用到这么一个结论:只用处理质数,不用处理合数。因为合数可以分解成几个比它本身小的质数的乘积,而这些肯定已经计算过了。因此可以 O(n)O(n) 计算出每个数对应的 pi−1pipi−1pi,令合数的对应值为 1,再求一次前缀积即可。这样就能 O(1)O(1) 回答查询了。
参考代码
思路
参考代码
传送门
思路
要完成这个题,首先要知道这么一个结论:若 gcd(a,b)=1gcd(a,b)=1,则 gcd(a,b+a)=1gcd(a,b+a)=1。结合辗转相除法的证明过程,这个结论显然。因此,题目中要求的东西为:
φ(m!)n!m!φ(m!)n!m!
展开得:
=m!(∏ipi−1pi)n!m!=n!(∏ipi−1pi)=m!(∏ipi−1pi)n!m!=n!(∏ipi−1pi)
其中pipi 表示 m!m! 的质因子。
n!n! 的阶乘可以 O(n)O(n) 预处理,后半部分需要用到这么一个结论:只用处理质数,不用处理合数。因为合数可以分解成几个比它本身小的质数的乘积,而这些肯定已经计算过了。因此可以 O(n)O(n) 计算出每个数对应的 pi−1pipi−1pi,令合数的对应值为 1,再求一次前缀积即可。这样就能 O(1)O(1) 回答查询了。
参考代码
#include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <iostream> #include <algorithm> #include <vector> #include <string> #include <stack> #include <queue> #include <deque> #include <map> #include <set> #include <bitset> #include <list> typedef int INT; using std::cin; using std::cout; using std::endl; INT readIn() { INT a = 0; bool minus = false; char ch = getchar(); while (!(ch == '-' || (ch >= '0' && ch <= '9'))) ch = getchar(); if (ch == '-') { minus = true; ch = getchar(); } while (ch >= '0' && ch <= '9') { a = a * 10 + (ch - '0'); ch = getchar(); } if (minus) a = -a; return a; } void printOut(INT x) { char buffer[20]; INT length = 0; if (x < 0) { putchar('-'); x = -x; } do { buffer[length++] = x % 10 + '0'; x /= 10; } while (x); do { putchar(buffer[--length]); } while (length); putchar('\n'); } const int maxn = int(1e7) + 5; int mod; int n, m; bool isntPrime[maxn]; int prime[maxn]; int fac[maxn]; int inv[maxn]; int mul[maxn]; void init() { isntPrime[1] = true; for (int i = 2; i <= int(1e7); i++) { if (!isntPrime[i]) prime[++prime[0]] = i; for (int j = 1; j <= prime[0] && i * prime[j] <= int(1e7); j++) { int t = i * prime[j]; isntPrime[t] = true; if (!(i % prime[j])) break; } } fac[0] = 1; for (int i = 1; i <= int(1e7); i++) fac[i] = (long long)fac[i - 1] * i % mod; inv[1] = 1; for (int i = 2; i <= int(1e7); i++) inv[i] = (long long)(mod - mod / i) * inv[mod % i] % mod; mul[1] = 1; for (int i = 2; i <= int(1e7); i++) if (isntPrime[i]) mul[i] = 1; else mul[i] = (long long)(i - 1) * inv[i] % mod; for (int i = 2; i <= int(1e7); i++) mul[i] = (long long)mul[i - 1] * mul[i] % mod; } void run() { int T = readIn(); mod = readIn(); init(); while (T--) { n = readIn(); m = readIn(); printOut((long long)fac * mul[m] % mod); } } int main() { run(); return 0; }
相关文章推荐
- BZOJ 2186: [Sdoi2008]沙拉公主的困惑( 数论 )
- 【数论】【欧拉函数】【筛法求素数】【乘法逆元】【快速幂取模】bzoj2186 [Sdoi2008]沙拉公主的困惑
- Bzoj 2186: [Sdoi2008]沙拉公主的困惑 乘法逆元,线性筛,欧拉函数,数论
- BZOJ 2186 SDOI2008 沙拉公主的困惑 数论
- [bzoj2186][Sdoi2008]沙拉公主的困惑_数论
- [bzoj2186][Sdoi2008]沙拉公主的困惑——数论
- BZOJ 2186 SDOI2008 沙拉公主的困惑 数论
- BZOJ2186 [Sdoi2008]沙拉公主的困惑 【数论,欧拉函数,线性筛,乘法逆元】
- 【bzoj2186】【sdoi2008】【沙拉公主的困惑】【数论】
- BZOJ2186 [Sdoi2008]沙拉公主的困惑 【数论,欧拉函数,线性筛,乘法逆元】
- bzoj2186【Sdoi2008】沙拉公主的困惑 数论:欧拉筛法,线性逆元
- [BZOJ2186][SDOI2008]沙拉公主的困惑(数论)
- bzoj 2186: [Sdoi2008]沙拉公主的困惑 数论
- 【SDOI2008】【BZOJ2186】【沙拉公主的困惑】【题解】【数论】
- bzoj 2186: [Sdoi2008]沙拉公主的困惑 (线性筛+数论)
- BZOJ 2186: [Sdoi2008]沙拉公主的困惑| 数论
- 【bzoj2186】[Sdoi2008]沙拉公主的困惑 数论 线性筛逆元
- [BZOJ2186][Sdoi2008]沙拉公主的困惑(数论)
- bzoj 2186: [Sdoi2008] 沙拉公主的困惑 (数论,逆元)
- BZOJ 2186 SDOI 2008 沙拉公主的困惑 数论