势能线段树

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


posted on 2021-09-30 11:42  xlinsist  阅读(43)  评论(0编辑  收藏  举报