勢能線段樹
阿新 • • 發佈:2021-09-30
The 2021 ICPC Asia Regionals Online Contest (II),PTA
#include <bits/stdc++.h> //#define endl '\n' #define lose {printf("NO\n");return;} #define win {printf("YES\n");return;} #define all(A) (A).begin(),(A).end() #define FOR(I, A, B) for (int I = (A); I <= (B); ++I) #define PER(I, A, B) for (int I = (A); I >= (B); --I) #define DB(A) cout<<(A)<<endl #define lson k*2 #define rson k*2+1 #define fi first #define se second #define PB push_back #define Pair pair<int,int> #define MP make_pair #define ll long long #define ull unsigned long long //#define int ll using namespace std; #define DB1(args...) do { cout << #args << " : "; dbg(args); } while (0) void dbg() { std::cout << " #\n"; } template<typename T, typename...Args> void dbg(T a, Args...args) { std::cout << a << ' '; dbg(args...); } template <typename T> void inline read(T &x) { int f = 1; x = 0; char s = getchar(); while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); } while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar(); x *= f; } template <typename T> void print(T x) { if (x < 0) { putchar('-'); print(x); return ; } if (x >= 10) print(x / 10); putchar((x % 10) + '0'); } template <typename T> void println(T x) { print(x); putchar('\n'); } //var const int maxn=1e5+10; const int MAX=1000; const int inf=0x3f3f3f3f; const int mod=998244353; //head int n,m; int c[maxn]; int cnt[maxn][30]; struct readtype { bitset<30> op; int val; } a[maxn]; /**********************************************************/ int pri[110]; int pvis[110]; int pnum=-1; void getprime() { FOR(i,2,100) { if (!pvis[i]) { pri[++pnum]=i; int j=i+i; while (j<=100) { pvis[j]=1; j+=i; } } } assert(pnum==24); } int phi(int n)//計算尤拉函式 { int ans = n; for(int i = 2; i * i <= n; ++i) { if(n % i == 0) { ans = ans / i * (i - 1); while(n % i == 0) n /= i; } } if(n > 1) ans = ans / n * (n - 1); return ans; } void init() { getprime(); FOR(i,1,100000) { int now=i; FOR(j,0,24) { while (now%pri[j]==0) { cnt[i][j]++; now/=pri[j]; } } } assert(cnt[16][0]==4); assert(cnt[18][0]==1); assert(cnt[18][1]==2); FOR(i,1,n) { a[i].op.reset(); a[i].val=phi(c[i]); FOR(j,0,24) if (cnt[c[i]][j]) a[i].op.set(j); } } int add(int a,int b) { int c=a+b; if (c>=mod) c-=mod; return c; } int mul(int a,int b) { ll c=1ll*a*b%mod; return (int)c; } int fpow(int x,int k) { int ans=1; while (k) { if (k&1) ans=mul(ans,x); k>>=1; x=mul(x,x); } return ans; } struct tree { int l,r; bitset<30>op; int w; int z; } t[maxn*4]; void pushup(int k) { t[k].op=t[lson].op&t[rson].op; t[k].z=add(t[lson].z,t[rson].z); } void pushdown(int k) { int w=t[k].w; if (w==1) return; t[lson].w=mul(t[lson].w,w); t[rson].w=mul(t[rson].w,w); t[lson].z=mul(t[lson].z,w); t[rson].z=mul(t[rson].z,w); t[k].w=1; } void build(int k,int l,int r) { t[k].l=l,t[k].r=r,t[k].w=1; if (l==r) { t[k].op=a[l].op; t[k].z=a[l].val; return; } int mid=(l+r)>>1; build(lson,l,mid); build(rson,mid+1,r); pushup(k); } void update(int k,int l,int r,int p,int num) { // DB1(k,t[k].l,t[k].r,l,r); if (t[k].l==l&&t[k].r==r&&t[k].op[p]) { int tmp=fpow(pri[p],num); t[k].w=mul(t[k].w,tmp); t[k].z=mul(t[k].z,tmp); return; } if (t[k].l==t[k].r) { t[k].z=mul(t[k].z,pri[p]-1); int tmp=fpow(pri[p],num-1); t[k].z=mul(t[k].z,tmp); t[k].op[p]=1; return; } pushdown(k); int mid=(t[k].l+t[k].r)>>1; if (r<=mid) update(lson,l,r,p,num); else if (l>mid) update(rson,l,r,p,num); else { update(lson,l,mid,p,num); update(rson,mid+1,r,p,num); } pushup(k); } int query(int k,int l,int r) { // DB1(k,t[k].l,t[k].r,l,r); if (t[k].l==l&&t[k].r==r) { return t[k].z; } pushdown(k); int mid=(t[k].l+t[k].r)>>1; if (r<=mid) return query(lson,l,r); else if (l>mid) return query(rson,l,r); else { int tmp1=query(lson,l,mid); int tmp2=query(rson,mid+1,r); return add(tmp1,tmp2); } } void solve() { read(n);read(m); FOR(i,1,n) { read(c[i]); } init(); build(1,1,n); vector<int>ans; // FOR(i,1,n) DB1(i,a[i].val); FOR(i,1,m) { int op; scanf("%d",&op); if (op==0) { int x,y,w; scanf("%d%d%d",&x,&y,&w); FOR(j,0,24) if (cnt[w][j]) { update(1,x,y,j,cnt[w][j]); } } else { int l,r; scanf("%d%d",&l,&r); ans.PB(query(1,l,r)); } } int anslen=ans.size(); FOR(i,0,anslen-1) { printf("%d",ans[i]); if (i!=anslen-1) printf("\n"); } } signed main() { // freopen("read.txt", "r", stdin); // freopen("ans.txt", "w", stdout); int TestCase = 1; //cin>>TestCase; while (TestCase--) { solve(); } }