您的位置:首页 > 其它

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) 回答查询了。

参考代码

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: