首先想累乘该怎么做,我们可以记录k的所有质因子与他们的幂次。
在用线段树记录l~r里k的所有质因子的幂次,答案即为l到r里k的质因子的幂次除以k自己的幂次的最小值。
但是题目要求是阶乘累乘,那我们可以想到分解阶乘具体为
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue>
#include<stack>
#include<unordered_map>
#include<map>
#include<cstdio>
#include<cmath>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
using pii=pair<int,int>;
const int N = 2e5+10;
int t,n,m,q,a[N],k,l,r,p,x;
unordered_map<int,ll>ci;
/*typedef struct mat{
ll jz[3][3]={0};
mat operator*(struct mat a){
ll s[3][3];
mat res;
memcpy(s,jz,sizeof jz);
for(int i=1;i<=2;i++)
for(int j=1;j<=2;j++)
for(int k=1;k<=2;k++)
res.jz[i][j]=(res.jz[i][j]+jz[i][k]*a.jz[k][j]%mod)%mod;
return res;
}
}mat;
mat base;
inline void ksm(mat& res,int u){
while(u){
if(u&1)res=res*base;
u>>=1;
base=base*base;
}
}*/
struct xds{
int l,r;
int x;
unordered_map<int,ll>ci;
}tr[N*4];
inline void add(int u,int s){
for(auto it =ci.begin();it!=ci.end();it++)
{
ll a=it->first;
ll res=a;
if(res>s)break;
ll ans(0);
while(res<=s)
{
ans+=s/res;
res*=a;
}
tr[u].ci[a]+=ans;
}
}
inline void del(int u,int s){
for(auto it =ci.begin();it!=ci.end();it++)
{
ll a=it->first;
ll res=a;
if(res>s)break;
ll ans(0);
while(res<=s)
{
ans+=n/res;
res*=a;
}
tr[u].ci[a]-=ans;
}
}
inline void pushup(int u){
tr[u].ci.clear();
for(auto it =tr[u<<1].ci.begin();it!=tr[u<<1].ci.end();it++){
ll a=it->first,b=it->second;
tr[u].ci[a]+=b;
}
for(auto it =tr[u<<1|1].ci.begin();it!=tr[u<<1|1].ci.end();it++){
ll a=it->first,b=it->second;
tr[u].ci[a]+=b;
}
}
inline void build(int u,int l,int r)
{
if(l==r){
tr[u]={l,r,a[r]};
add(u,a[r]);
}
else{
tr[u]={l,r};
int mid=l+r>>1;
build(u<<1,l,mid),build(u<<1|1,mid+1,r);
pushup(u);
}
}
inline void modify(int u,int x,int v){
if(tr[u].l==tr[u].r){
if(v!=tr[u].x){
tr[u].ci.clear();
tr[u].x=v;
add(u,v);
}
}
else {
int mid=tr[u].l+tr[u].r>>1;
if(x<=mid)modify(u<<1,x,v);
else modify(u<<1|1,x,v);
pushup(u);
}
}
unordered_map<int,ll>ans;
inline void add(int u){
for(auto it=tr[u].ci.begin();it!=tr[u].ci.end();it++){
ll a=it->first,b=it->second;
ans[a]+=b;
}
}
void query(int u,int l,int r){
if(tr[u].l>=l&&tr[u].r<=r){
add(u);
}
else {
int mid=tr[u].l+tr[u].r>>1;
if(l<=mid)query(u<<1,l,r);
if(r>mid)query(u<<1|1,l,r);
}
}
int main(){
scanf("%d%d%d",&n,&m,&k);
int s=k;
for(int i(2);i<=s/i;i++){
if(s%i==0){
int t=0;
while(s&&s%i==0){
s/=i;t++;
}
ci[i]=t;
}
}
if(s>1)ci[s]=1;
for(int i(1);i<=n;i++)scanf("%d",&a[i]);
build(1,1,n);
while(m--){
int op;
scanf("%d",&op);
if(op==2){
scanf("%d%d",&l,&r);
ans.clear();
query(1,l,r);
ll res=1e18;
for(auto it=ci.begin();it!=ci.end();it++){
res=min(res,ans[it->first]/it->second);
}
printf("%lld\n",res);
}
else{
scanf("%d%d",&p,&x);
modify(1,p,x);
}
}
}