翻译: 求区间乘积的phi函数值,其中区间中的数的质因数只有60种。带单点修改操作。
明显质因数比较少,勉强可以压一压开一个int64就压住了。
已知
所以易以60的常数求出答案
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<queue>
#include<stack>
#include<map>
#include<set>
using namespace std;
typedef int INT;
#define int long long
#define lc (p<<1)
#define rc (p<<1|1)
const int N=100000+1000;
const int mod=19961993;
inline void read(int &x){
x=0;
int f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=x*10+ch-'0';
ch=getchar();
}
x*=f;
}
//
int vis[N]={};
int Prime[N]={};
int cnt=0;
void Pre(){
for(int i=2;i<=281;i++){
if(!vis[i]){
cnt++;
Prime[cnt]=i;
}
for(int j=1;j<=cnt&&Prime[j]*i<=281;j++){
vis[i*Prime[j]]=1;
if(i%Prime[j]==0)break;
}
}
}
int inv[N]={};
//
struct Node{
int lson,rson,ans,Mx;
}T[N<<2],tmp;
inline void PushUp(int p){
T[p].ans=T[lc].ans*T[rc].ans%mod;
T[p].Mx=(T[lc].Mx|T[rc].Mx);
}
inline void build(int p,int l,int r){
T[p].lson=l;
T[p].rson=r;
if(l==r){
T[p].ans=3;
T[p].Mx=2;
return;
}
int mid=(l+r)/2;
build(lc,l,mid);
build(rc,mid+1,r);
PushUp(p);
}
inline void Update(int p,int pos,int ans){
// cout<<p<<" "<<pos<<" "<<ans<<'\n';
if(T[p].lson==pos&&T[p].rson==pos){
// cout<<"p= "<<p<<'\n';
T[p].ans=ans;
T[p].Mx=0;
for(int i=0;i<60;i++){
// cout<<i<<" ";
if(ans%Prime[i+1]==0){
// cout<<"iC= "<<Prime[i+1]<<'\n';
T[p].Mx|=(((int)1)<<i);
}
}
return;
}
int mid=(T[p].lson+T[p].rson)/2;
if(pos<=mid)Update(lc,pos,ans);
else Update(rc,pos,ans);
PushUp(p);
}
inline void Query(int p,int l,int r){
// cout<<T[p].ans<<" "<<T[p].lson<<" "<<T[p].rson<<'\n';
if(l<=T[p].lson&&T[p].rson<=r){
tmp.ans=tmp.ans*T[p].ans%mod;
tmp.Mx|=T[p].Mx;
return;
}
int mid=(T[p].lson+T[p].rson)/2;
if(l<=mid)Query(lc,l,r);
if(mid<r )Query(rc,l,r);
}
int n;
inline int quick_pow(int x,int k){
int ret=1;
while(k){
if(k%2==1){
ret=ret*x%mod;
}
x=x*x%mod;
k=k/2;
}
return ret;
}
INT main(){
//freopen("3717.in","r",stdin);
read(n);
Pre();
for(int i=1;i<=60;i++){
// cout<<Prime[i]<<" ";
inv[i]=quick_pow(Prime[i],mod-2)*(Prime[i]-1)%mod;
}
build(1,1,100000);
for(int i=1;i<=n;i++){
int opt;
read(opt);
int x,y;
read(x);
read(y);
if(opt==0){
tmp.ans=1;
tmp.Mx=0;
Query(1,x,y);
int ans=tmp.ans;
// cout<<tmp.ans<<" ";
for(int i=0;i<60;i++){
if(tmp.Mx&((int)1<<i)){
// cout<<i<<'\n';
ans=ans*inv[i+1]%mod;
}
}
cout<<ans<<'\n';
}
else{
Update(1,x,y);
}
}
}
本文介绍了一种求解区间内数的欧拉函数乘积的方法,特别针对那些质因数较少的情况,如只有60种质因数。通过预处理质数,并使用线段树进行区间查询和单点更新,实现高效算法。
933

被折叠的 条评论
为什么被折叠?



