luoguP3601 签到题 质因数分解+欧拉函数
题不难,但是求欧拉函数的部分要注意一下:
求欧拉函数的时候是没有必要取模的,因为一定能除开.
如果取模的话由于出题人没有保证存在逆元会出现错误.
由于 $[L,R]$ 区间大小不超过 $10^6$,然后每个数最多只有一个大于根号 R 的质因子,所以可以筛出来 $10^6$
以内的质因数,然后调和级数来更新答案.
code:
#include <bits/stdc++.h>
#define N 1000009
#define ll long long
#define mod 666623333
#define setIO(s) freopen(s".in","r",stdin)
using namespace std;
ll L,R;
bool vis[N];
vector<int>g[N];
int prime[N],inv[N],cnt;
ll qpow(ll x,ll y)
{
ll tmp=1;
for(;y;y>>=1,x=x*x%mod) if(y&1) tmp=tmp*x%mod;
return tmp;
}
ll INV(ll x) { return qpow(x,mod-2); }
void init()
{
for(int i=2;i<N;++i)
{
if(!vis[i]) prime[++cnt]=i;
for(int j=1;j<=cnt&&prime[j]*i<N;++j)
{
vis[i*prime[j]]=1;
if(i%prime[j]==0) break;
}
}
inv[1]=1;
for(int i=2;i<N;++i) inv[i]=(ll)(mod-mod/i)*inv[mod%i]%mod;
}
ll U(ll x,ll y) { return x%y==0?x/y:x/y+1;}
int main()
{
// setIO("input");
scanf("%lld%lld",&L,&R);
init();
for(int i=1;i<=cnt;++i)
{
if(1ll*prime[i]*prime[i]>R) break;
for(ll j=U(L,prime[i])*1ll*prime[i];j<=R;j+=prime[i])
g[j-L+1].push_back(prime[i]);
}
ll fin=0;
for(int i=1;i<=R-L+1;++i)
{
ll cur=1ll*i+L-1;
ll an=cur;
for(int j=0;j<g[i].size();++j)
{
an=an/g[i][j]*(g[i][j]-1);
while((cur%g[i][j])==0) cur/=g[i][j];
}
if(cur>1) an=an/cur*(cur-1);
(fin+=1ll*i+L-1+mod-an)%=mod;
}
printf("%lld\n",fin);
return 0;
}

浙公网安备 33010602011771号