当前位置: 代码迷 >> 综合 >> Codeforces Round #538 (Div. 2)F Please, another Queries on Array? (数论+线段树+状态压缩)
  详细解决方案

Codeforces Round #538 (Div. 2)F Please, another Queries on Array? (数论+线段树+状态压缩)

热度:40   发布时间:2023-11-15 12:41:13.0

题目链接:http://codeforces.com/contest/1114

题目大意:

查询结构,
初始给定一个序列,支持两种操作,
一种是 在区间上每个数都乘上一个x,
一种是查询区间上每个数累乘后的结果的欧拉函数。

题目分析: 

这道题应该是 比较简单的,
主要感觉还是考验代码功底吧。
观察欧拉函数的性质即可,
euler(n)=n*{因子乘积(1-1/p)}形式,
打表发现300以内的质数个数刚好是62,用long long存的下,
那么不难想到,开两颗线段树,一颗维护前面的n,就是普通的区间乘积形式,
另一种是维护区间中包含的质因子的形式,这方面可以用状压表示该区间到底存放了哪些质因子,
关于质因子区间性质对应位运算应该是或运算。
两种区间性质都清楚了代码结构就清楚了,注意逆元最好预处理下不然可能超时。

#include<bits/stdc++.h>
using namespace std;#define debug puts("YES");
#define rep(x,y,z) for(int (x)=(y);(x)<(z);(x)++)
#define ll long long#define lrt int l,int r,int rt
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define root l,r,rt
#define mst(a,b) memset((a),(b),sizeof(a))
#define pii pair<int,int>
#define fi first
#define se second
#define mk(x,y) make_pair(x,y)
const int mod=1e9+7;
const int maxn=4e5+10;
const int ub=1e6;
const double inf=1e-4;
ll powmod(ll x,ll y){ll t; for(t=1;y;y>>=1,x=x*x%mod) if(y&1) t=t*x%mod; return t;}
ll gcd(ll x,ll y){return y?gcd(y,x%y):x;}
/*
题目大意:
查询结构,
初始给定一个序列,支持两种操作,
一种是 在区间上每个数都乘上一个x,
一种是查询区间上每个数累乘后的结果的欧拉函数。题目分析:
这道题应该是 比较简单的,
主要感觉还是考验代码功底吧。
观察欧拉函数的性质即可,
euler(n)=n*{因子乘积(1-1/p)}形式,
打表发现300以内的质数个数刚好是62,用long long存的下,
那么不难想到,开两颗线段树,一颗维护前面的n,就是普通的区间乘积形式,
另一种是维护区间中包含的质因子的形式,这方面可以用状压表示该区间到底存放了哪些质因子,
关于质因子区间性质对应位运算应该是或运算。
两种区间性质都清楚了代码结构就清楚了,注意逆元最好预处理下不然可能超时。*/int p[400],vis[400],tot=0;
ll inv[301];
void sieve(){rep(i,2,300){if(!vis[i]) p[tot++]=i;rep(j,0,tot){if(1LL*i*p[j]>=300) break;vis[i*p[j]]=1;if(i%p[j]==0) break;}}mst(inv,0),inv[0]=inv[1]=1;for(int i=2;i<301;i++) inv[i]=1LL*(mod-mod/i)*inv[mod%i]%mod;///cout<<inv[59]<<" "<<powmod(59LL,mod-2)<<endl;
}
int n,m,x;
ll a[maxn],b[maxn];
struct seg{ll tree[maxn<<2],lazy[maxn<<2];int flag;void build(lrt){lazy[rt]=flag;if(l==r){if(flag) tree[rt]=b[l];else tree[rt]=a[l];return ;}int mid=l+r>>1;build(lson),build(rson);if(flag) tree[rt]=tree[rt<<1]*tree[rt<<1|1]%mod;else tree[rt]=tree[rt<<1]|tree[rt<<1|1];}void pushdown(int l,int r,int rt){int mid=l+r>>1;if(lazy[rt]!=flag){if(flag){(lazy[rt<<1]*=lazy[rt])%=mod;(lazy[rt<<1|1]*=lazy[rt])%=mod;tree[rt<<1]=tree[rt<<1]*powmod(lazy[rt],mid-l+1)%mod;tree[rt<<1|1]=tree[rt<<1|1]*powmod(lazy[rt],r-mid)%mod;}else{lazy[rt<<1]|=lazy[rt];lazy[rt<<1|1]|=lazy[rt];tree[rt<<1]|=lazy[rt];tree[rt<<1|1]|=lazy[rt];}lazy[rt]=flag;}}void update(lrt,int L,int R,ll v){if(L<=l&&r<=R){if(flag)tree[rt]=tree[rt]*powmod(v,r-l+1)%mod;else tree[rt]|=v;if(flag) (lazy[rt]*=v)%=mod;else lazy[rt]|=v;return ;}pushdown(l,r,rt);int mid=l+r>>1;if(L<=mid)update(lson,L,R,v);if(mid<R) update(rson,L,R,v);if(flag) tree[rt]=tree[rt<<1]*tree[rt<<1|1]%mod;else tree[rt]=tree[rt<<1]|tree[rt<<1|1];}ll query(lrt,int L,int R){if(L<=l&&r<=R)  return tree[rt];int mid=l+r>>1;pushdown(l,r,rt);ll ans=flag;if(L<=mid){if(flag) ans=ans*query(lson,L,R)%mod;else ans|=query(lson,L,R);}if(mid<R){if(flag) ans=ans*query(rson,L,R)%mod;else ans|=query(rson,L,R);}return ans;}
}tree1,tree2;
int main(){sieve();cin>>n>>m;rep(i,1,n+1){cin>>x;b[i]=x;///a[i]=0;for(int j=2;j<=x;j++)if(x%j==0){int pos=lower_bound(p,p+tot,j)-p;while(x%j==0) x/=j;a[i]|=1LL<<pos;}}tree1.flag=1,tree2.flag=0;tree1.build(1,n,1);tree2.build(1,n,1);rep(i,0,m){char op[20];scanf("%s",op);int x,y,z;if(op[0]=='T'){cin>>x>>y;ll ret=tree2.query(1,n,1,x,y),ans=tree1.query(1,n,1,x,y);rep(j,0,tot) if((1LL<<j)&ret)///这里有点玄学,用==1LL就不行ans=ans*(p[j]-1)%mod*inv[p[j]]%mod;cout<<ans<<endl;}else{cin>>x>>y>>z;tree1.update(1,n,1,x,y,z);ll sta=0;for(int j=2;j<=z;j++)if(z%j==0){int pos=lower_bound(p,p+tot,j)-p;sta|=1LL<<pos;while(z%j==0) z/=j;}tree2.update(1,n,1,x,y,sta);}}return 0;
}

 

  相关解决方案