SSL2837 2017年11月6日提高组T1 互质(math)
来源:互联网 发布:linux新增硬盘分区命令 编辑:程序博客网 时间:2024/06/10 11:04
2017年11月6日提高组T1 互质
Description
对于两个整数k 和m,如果k 和m 的最大公约数为1,则k 和m 互质。给出两个正整
数n 和m(m≤n),定义f(n,m)为1~n!中与m!互质的数的个数。其中n!=1*2*3*..*(n-1)*n。
Task:给定n 和m,要求计算f(n,m)。
Input
本题设多组数据。
输入文件的第一行有一个整数T(1≤T≤100000),表示有T 组数据。
接下来有T 行,每行两个整数n 和m(2≤n≤100000,2≤m≤n)。
Output
输出文件包含T 行,每行一个整数,表示f(n,m)。
由于答案过大,所以你只要输出f(n,m) mod 131071。
131071 是M17(梅森素数,2^17-1)。
Sample Input
1
3 2
Sample Output
3
Hint
对于100%的数据,1≤T≤100000,2≤N≤100000
AcFast 友情提示:小心运算溢出,也就是RTE215 错误
分析:首先,令n=N!,m=M!
∵M<=N
∴m|n,所以问题化为求1-n中与m互质的数的个数,即(n/m)*phi(m),其正确性是显然的。
如果一个数x< m且和m互质,即gcd(x,m)=1,那么gcd(x+km,m)=1,假设x+km和m不互质,那么一定存在一个m的因数y,使得y也是x+km的因数,即能写成y(x/y+km/y),但是x中没有y这个因子,
∴假设不成立
∴gcd(x+km,m)=1,对于每一个小于m的和m互质的数,都能用这个式子退出剩下的大于m小于等于n且和m互质的数,于是我们得到ans=(n/m)phi(m),这样是否包含了所有的答案呢?
可以知道对于任意一个与m互质的数,减去km一定能得到m以内的一个和m互质的数,因此上式包含了所有的符合要求的数
由于M!是阶乘,所以phi(i)=M!(1-1/p1)(1-1/p2)…(1-1/pk),1到pk是小于等于M的所有素数,O(MloglogM)筛出,约去M!得ans=N!(1-1/p1)(1-1/p2)…(1-1/pk),所有的N!都可以在O(N)的预处理求出,因为要modR,所以需要求p1到pk的逆元。
我们观察式子:ans=N!(1-p1/1)(1-p2/1)…(1-pk/1),对于不同的询问,只有N!和k不同,既然能够预处理N!,何不预处理后面的乘积?进行O(M)的预处理,每次回答的复杂度降为O(1)。
代码
#include <cstdio>#define N 100005#define mo 131071#define ll long longusing namespace std;ll p[N],ny[N],jc[N],phi[N];ll n,m,tot;bool f[N]; ll power(ll a,ll b){ ll r=1,base=a; while (b) { if (b&1) r=r*base%mo; base=base*base%mo; b>>=1; } return r;}int main(){// freopen("a.in","r",stdin);// freopen("a.out","w",stdout); int T; scanf("%d",&T); jc[1]=ny[1]=1; for (int i=2;i<=100000;i++) { jc[i]=jc[i-1]*i%mo; ny[i]=power(i,mo-2); } f[1]=true; for (int i=2;i<=100000;i++) { if (!f[i]) p[++tot]=i; for (int j=1;j<=tot;j++) { if (p[j]*i>100000) break; f[p[j]*i]=true; if (i%p[j]==0) break; } } int x=0,q=1; phi[1]=1; while (1) { q++; if (q>100000) break; if (q==p[x+1]) { x++; if (x>tot) break; phi[q]=phi[q-1]*(p[x]-1)%mo*ny[p[x]]%mo; continue; } phi[q]=phi[q-1]; } while (T--) { scanf("%lld%lld",&n,&m); printf("%lld\n",jc[n]*phi[m]%mo); }}
- SSL2837 2017年11月6日提高组T1 互质(math)
- SSL2694 2017年8月15日提高组T1 字符串(math,组合数取模)
- SSL2705 2017年8月17日提高组T1 游戏(math+二分)
- SSL2783 2017年10月23日提高组T1 摆书(math)
- SSL2838 2017年11月6日提高组T1 矩阵(贪心)
- SSL2839 2017年11月6日提高组T1 游戏(dp)
- 2017年11月2日提高组T1 Sequence
- 2017年11月4日提高组T1 背包
- SSL2828 2017年11月2日提高组T1 Sequence(kmp)
- SSL2831 2017年11月3日提高组T1 跃动(dp)
- SSL2832 2017年11月3日提高组T1 生日宴会(二分)
- SSL2833 2017年11月3日提高组T1 Alice的疑问(数位dp)
- SSL2846 2017年11月9日提高组T1 质数(线性筛)
- 2017年8月7日提高组T1 呵呵
- 2017年8月7日提高组T1 呵呵
- 2017年8月7日提高组T1 呵呵
- 2017年8月7日提高组T1 根
- 2017年8月8日提高组T1 作业
- POJ 3162 浅谈尺取法区间问题运用及多源树上路径统计
- 多层感知机:Multi-Layer Perceptron
- Linux网络编程--(7)广播和组播
- Codeforces Round #877 (Div. 2) B.
- sql语言简单应用
- SSL2837 2017年11月6日提高组T1 互质(math)
- AVL树
- VINS技术路线与代码详解
- 用栈来进行数字的进制转换
- Oracle:时间戳
- Dialvik/ARP(ANDROID)中的多线程机制(2)
- netty对http协议解析原理解析
- 【减治法】插入排序及C++代码实现
- 基础练习 完美的代价(蓝桥杯 字符串问题)