奇数国

  大半夜罗了奇怪的做法,发现M啦QAQ,内心死亡,然而第二天早上写完另一种发现交的代码是nn=4,内心死亡again

  首先从题意分析就是,线段树上罗,然后求欧拉函数

  两种做法的区别在于求的公式不同

  第一种是,phi(x)=sigma(pn-1)pn^(an-1),其中pn为对x分解质因数

  这种做法需要记录每个因数的个数,所以奇慢

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define lson rt<<1,l,mid
 5 #define rson rt<<1|1,mid+1,r
 6 #define maxn 100005
 7 #define mod 19961993
 8 typedef long long i64;
 9 struct node{
10     int v[61];
11     void clear(){memset(v,0,sizeof(v));}
12     node operator+(const node &t)const{
13         node tmp;
14         tmp.v[0]=0;//
15         for(int i=1;i<=60;i++)
16             tmp.v[i]=v[i]+t.v[i];
17         return tmp;
18     }
19 
20 }tree[maxn<<2],tmp;
21 i64 prime[]={0,2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281};
22 int nn=100000;
23 int read(){
24     int haha=0;
25     char ch=0;
26     while(!isdigit(ch))ch=getchar();
27     while(isdigit(ch)){
28         haha=haha*10+ch-'0';
29         ch=getchar();
30     }
31     return haha;
32 }
33 node div(int x){
34     node t;
35     t.v[0]=0;//
36     for(int i=1;i<=60;i++){
37         t.v[i]=0;
38         while(x&&x%prime[i]==0)
39             t.v[i]++,x/=prime[i];
40     }
41     return t;
42 }
43 void update(int rt,int l,int r,int pos,int x){
44     if(l==r){
45         tree[rt]=div(x);
46         return;
47     }
48     int mid=(l+r)>>1;
49     if(pos<=mid)update(lson,pos,x);
50     else update(rson,pos,x);
51     tree[rt]=tree[rt<<1]+tree[rt<<1|1];
52 }
53 void query(int rt,int l,int r,int ql,int qr){
54     if(ql<=l&&qr>=r){
55         tmp=tmp+tree[rt];
56         return;
57     }
58     int mid=(l+r)>>1;
59     if(ql<=mid)query(lson,ql,qr);
60     if(qr>mid)query(rson,ql,qr);
61 }
62 i64 qp(i64 bs,int x){
63     i64 ans=1;
64     while(x){
65         if(x&1)ans=(ans*bs)%mod;
66         bs=(bs*bs)%mod;
67         x>>=1;
68     }
69     return ans;
70 }
71 int main(){
72     for(int i=1;i<=nn;i++)
73         update(1,1,nn,i,3);
74     int n,op,a,b;
75     n=read();
76     for(int i=1;i<=n;i++){
77         op=read(),a=read(),b=read();
78         if(!op){
79             tmp.clear();
80             query(1,1,nn,a,b);
81             i64 ans=1LL;
82             for(int j=1;j<=60;j++)
83                 if(tmp.v[j])
84                     ans=(ans*((prime[j]-1)*qp(prime[j],tmp.v[j]-1))%mod)%mod;
85             printf("%lld
",ans);//
86         }
87         else update(1,1,nn,a,b);
88     }
89     return 0;
90 }
View Code

  

  第二种是phi(x)=x*(p1-1)/p1*(p2-1)/p2*...*(pn-1)/pn

  这玩意只需要知道x的因数有哪些,可以压到一个long long里,因为有除法,所以会用到乘法逆元

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 
 4 typedef long long i64;
 5 #define lson rt<<1,l,mid
 6 #define rson rt<<1|1,mid+1,r
 7 #define mod 19961993
 8 #define maxn 100005
 9 const int nn=100000;
10 i64 prime[]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281};
11 i64 am,ap,pri[maxn<<2],mul[maxn<<2],ni[60];
12 
13 int read(){
14     int tmp=0;
15     char ch=0;
16     while(!isdigit(ch))ch=getchar();
17     while(isdigit(ch)){
18         tmp=tmp*10+ch-'0';
19         ch=getchar();
20     }
21     return tmp;
22 }
23 i64 div(int x){
24     i64 haha=0;
25     for(int i=0;i<60;i++)
26         if(x%prime[i]==0)haha|=(1LL<<i);
27     return haha;
28 }
29 void update(int rt,int l,int r,int pos,int x){
30     if(l==r){
31         mul[rt]=x%mod;
32         pri[rt]=div(x);
33         return;
34     }
35     int mid=(l+r)>>1;
36     if(pos<=mid)update(lson,pos,x);
37     else update(rson,pos,x);
38     mul[rt]=(mul[rt<<1]*mul[rt<<1|1])%mod;
39     pri[rt]=pri[rt<<1]|pri[rt<<1|1];
40 }
41 void query(int rt,int l,int r,int ql,int qr){
42     if(ql<=l&&qr>=r){
43         am=(am*mul[rt])%mod;
44         ap|=pri[rt];
45         return;
46     }
47     int mid=(l+r)>>1;
48     if(ql<=mid)query(lson,ql,qr);
49     if(qr>mid)query(rson,ql,qr);
50 }
51 i64 qp(i64 bs,int x){
52     i64 sum=1LL;
53     while(x){
54         if(x&1)sum=(sum*bs)%mod;
55         bs=(bs*bs)%mod;
56         x>>=1;
57     }
58     return sum;
59 }
60 int main(){
61     for(int i=0;i<60;i++)
62         ni[i]=qp(prime[i],mod-2);
63     for(int i=1;i<=nn;i++)
64         update(1,1,nn,i,3);
65     int n,op,a,b;
66     n=read();
67     for(int i=1;i<=n;i++){
68         op=read(),a=read(),b=read();
69         if(!op){
70             am=1LL,ap=0;
71             query(1,1,nn,a,b);
72             for(int j=0;j<60;j++)
73                 if(ap&(1LL<<j))am=(am*((prime[j]-1)*ni[j])%mod)%mod;
74             printf("%lld
",am);
75         }
76         else update(1,1,nn,a,b);
77     }
78     return 0;
79 }
View Code
原文地址:https://www.cnblogs.com/Ngshily/p/5085193.html