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; }