Problem D
Help Mr. Tomisu
Input: Standard Input
Output: Standard Output
After wasting a significant time of his life in problem-setting, Mr. Tomisu is now searching for glory: A glory that will make him famous likeGoldbach and rich like Bill Gates :). And he has chosen the field of Number Theory as his prime interest. His creator did not make him very bright and so he needs your help to solve an elementary problem, using which he will begin his pursuit for glory!
Tomisu has come to know that finding out numbers having large prime factors are very important in cryptography. Given two integers N and M,he aims to count the number of integers x between 2 and N! (factorial N), having the property that all prime factors of x are greater than M.
Input
The input file contains at most 500 lines of inputs. Each line contains two integers N (1<N<10000001) and M (1≤M≤N and N-M≤100000). Input is terminated by a line containing two zeroes. This line should not be processed.
Output
For each line of input produce one line of output. This line contains the value T % 100000007 (Modulo 100000007 value of T). Here T is the total number of numbers between 1 and N! (factorial N) which have prime factors greater than M.
100 10 100 20 10000 9000 0 0 |
43274465 70342844 39714141 |
Problemsetter: Shahriar Manzoor
Special Thanks: Per Austrin
题目大意
求在1~N!之中,其所有质因数都大于M的数字个数。
解题思路
刚开始想到用容斥原理,处理数字中有偶数个不符合要求的质因数个数的,减去奇数个不符合要求质因数个数的。
对于每一个质因数都处理一下
TLE……
最后发现
N (1<N<10000001) and M (1≤M≤N and N-M≤100000).
500组数据,之前线性的处理方法也会直接挂
处理样例的数据发现答案是
(100!*48/210-1)mod 100000007
210 和 48 间的关系就是欧拉函数了……
换种思路,就是不超过M的所有质数的乘积P,所有数字种与P互质的个数,便是欧拉函数的典型应用了。(若不互质就拥有的小于等于M的质因数)
于是我们可以处理前k个质数的乘积,算出他们的欧拉函数(每个质数减一之积)。
就可以直接愉快的使用逆元了。
PS:由于UVa不限内存……可以直接把一些数据放在内存里咯,运行更快一些。
TLE的容斥代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <ctime>
#include <cctype>
#include <cmath>
#include <string>
#include <cstring>
#include <stack>
#include <queue>
#include <list>
#include <vector>
#include <map>
#include <set>
#define sqr(x) ((x)*(x))
#define LL long long
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define eps 1e-10
#define mod 100000007ll
using namespace std;
int co[100005];
LL pri[100005],pn;
void egcd(LL a,LL b,LL &x,LL &y)
{
if (b==0)
{
x=1,y=0;
return ;
}
egcd(b,a%b,x,y);
int t=x;
x=y,y=t-a/b*y;
}
int main()
{
LL n,m;
pn=0;
for (int i=2;i<=100000;i++)
{
if (co[i]==0) {
pri[++pn]=i;
for (int j=2*i;j<=100000;j+=i)
co[j]=1;
}
}
while (~scanf("%lld%lld",&n,&m),n+m)
{
LL t=1;
for (LL i=1;i<=n;i++)
t=t*i%mod;
LL preodd=0;
LL preeven=t;
LL ansodd,anseven;
for (LL i=1;pri[i]<=m;i++)
{
LL x,y,di;
egcd(pri[i],mod,x,y);
// printf("%lld %lld \n", pri[i],i);
di=(x+mod)%mod;
ansodd=(preeven*di)%mod;//枚举之前的奇偶
anseven=(preodd*di)%mod;
ansodd=(ansodd+preodd)%mod;
anseven=(anseven+preeven)%mod;
// printf("%lld \n", ansodd);
// printf("%lld \n", anseven);
preeven=anseven;//保存下来
preodd=ansodd;
}
LL ans=(-ansodd+anseven+mod-1)%mod;
printf("%lld\n",ans);
}
return 0;
}
AC代码:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <ctime>
#include <cctype>
#include <cmath>
#include <string>
#include <cstring>
#include <stack>
#include <queue>
#include <list>
#include <vector>
#include <map>
#include <set>
#define sqr(x) ((x)*(x))
#define LL long long
#define INF 0x3f3f3f3f
#define PI acos(-1.0)
#define eps 1e-10
#define mod 100000007ll
using namespace std;
int co[10000115];
LL pri[10000115],pn;
LL fac[10000115];
LL ff[1000115];
LL fm[1000115];
void egcd(LL a,LL b,LL &x,LL &y)
{
if (b==0)
{
x=1,y=0;
return ;
}
egcd(b,a%b,x,y);
int t=x;
x=y,y=t-a/b*y;
}
int main()
{
LL n,m;
pn=0;
for (int i=2;i<=10000107;i++)
{
if (co[i]==0)
pri[++pn]=i;
for (int j=1;(i*pri[j]<=10000107)&&(j<=pn);j++)
{
co[i*pri[j]]=1;
if (i%pri[j]==0) break;
}
}
fac[1]=1;
for (LL i=2;i<=10000107;i++)
fac[i]=(fac[i-1]*i)%mod;
ff[0]=1;
fm[0]=1;
for (int i=1;i<=pn;i++){
fm[i]=(fm[i-1]*pri[i])%mod;
ff[i]=(ff[i-1]*(pri[i]-1))%mod;}//fm[i]表示前i个质数的乘积,ff[i]表示对应的欧拉函数
while (~scanf("%lld%lld",&n,&m),n+m)
{
LL t=fac[n];
LL pt=upper_bound(pri+1,pri+pn+1,m)-pri;
if (pri[pt]>=m) pt--;
t=t*ff[pt]%mod;
LL x,y;
egcd(fm[pt],mod,x,y);
x=(x+mod)%mod;
t=(t*x-1+mod)%mod;
printf("%lld\n",t);
}
return 0;
}