拓展版:
题意:给定两个数和
,其中
,
,求
为质数的
有多少对?其中
和
的范
围是。
开始瞎BB:
对于本题,我们设
为满足
且
和
的
的对数
为满足
且
和
的
的对数
那么,很显然,反演后得到
因为题目要求是为质数,那么我们枚举每一个质数
,然后得到
如果直接这样做肯定TLE,那么我们必须优化。
我们设,那么继续得到
。
首先线性筛法的原理是枚举,小于等于的质数。
使得,即使得p[j]是k的最小质因数。 从而使得任何数只能由最小质因数转移过来,唯一了化转移方程,从而达到线性。
#include <iostream>
#include <cstring>
#include <string>
#include <vector>
#include <queue>
#include <cstdio>
#include <set>
#include <cmath>
#include <map>
#include <algorithm>
#define INF 0x3f3f3f3f
#define LL long long
#define Mod 10001
using namespace std;
#define MAXN 10000006
int mu[MAXN],prime[MAXN],top,f[MAXN],g[MAXN],sum[MAXN];
bool vis[MAXN];
const int UB=1e7;
void getmu()
{
int i,j,k;
mu[1]=1;
g[1]=0;
for(i=2; i<=UB; i++)
{
if(!vis[i])//单素数
{
prime[top++]=i;
mu[i]=-1;
g[i]=1;
}
for(j=0; (k=prime[j]*i)<=UB; j++)
{
vis[k]=1;
if(i%prime[j])//i=p2^a2*...pm^am
{
g[k]=mu[i]-g[i];
mu[k]=-mu[i];
}
else//i=p1^a1*...pm^am
{
mu[k]=0;
g[k]=mu[i];
break;
}
}
}
/*for(i=1;i<=100;i++)
{
sum=0;
for(j=2;j<=i;j++)
{
if(i%j==0&&!vis[j])
{
sum+=mu[i/j];
}
}
printf("%d:%d %d\n",i,sum,g[i]);///对拍
}*/
}
int main()
{
getmu();
int t=1;
//cin>>t;
//freopen("1.in","r",stdin);
//freopen("3.txt","w",stdout);
while(t--)
{
LL n,m;
//scanf("%lld%lld",&n,&m);
while(scanf("%lld",&n)!=EOF)
{
m=n;
if(n>m)
swap(n,m);
LL ans=0;
for(int i=1;i<=n;i++)
{
LL t=n/i;
ans=ans+(n/i)*(m/i)*g[i];
//cout<<n/i*m/i<<" "<<(n/i)*(m/i)<<endl;
}
cout<<ans<<endl;
}
}
return 0;
}
上式是2818的代码,改一下则为增强版