P5071 [Ynoi2015]此时此刻的光辉

传送门

lxl大毒瘤

首先一个数的因子个数就是这个数的每个质因子的次数+1的积,然后考虑把每个数分解质因子,用莫队维护,然后我交上去就0分了

如果是上面那样的话,我们每一次移动指针的时间复杂度是O(这个数的质因子个数),再加上我人傻常数大,T很正常……

于是按照memset0的说法,可以预处理质因子的前缀和,简单来说就是对于小于(sqrt{mx})的所有质因子维护前缀和,直接统计,大于的暴力在莫队的时候更新。因为每个数大于(sqrt{mx})的质因子个数为(O(1)),所以暴力更新的复杂度是(O(1))

然后我维护前缀和这里想岔了……死活没想明白怎么用前缀和更新答案……实际上就是用前缀和每一次暴力统计所有小于(sqrt{mx})的质因子个数,总共统计次数为(O(q)),所以这一部分的时间复杂度为(O(qsqrt{mx}))

然后加起来差不多是(O(nsqrt{n}))

//minamoto
#include<bits/stdc++.h>
#define R register
#define IT vector<node>::iterator
#define fp(i,a,b) for(R int i=a,I=b+1;i<I;++i)
#define fd(i,a,b) for(R int i=a,I=b-1;i>I;--i)
#define go(u) for(IT it=v[u].begin();it!=v[u].end();++it)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
using namespace std;
char buf[1<<21],*p1=buf,*p2=buf;
inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
int read(){
    R int res,f=1;R char ch;
    while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
    for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
    return res*f;
}
char sr[1<<21],z[20];int C=-1,Z=0;
inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
void print(R int x){
    if(C>1<<20)Ot();if(x<0)sr[++C]='-',x=-x;
    while(z[++Z]=x%10+48,x/=10);
    while(sr[++C]=z[Z],--Z);sr[++C]='
';
}
const int N=1e5+5,P=19260817;
struct node{
	int v,cnt;
	node(){}
	node(R int v,R int cnt):v(v),cnt(cnt){}
};vector<node>v[N];map<int,int>mp;map<int,int>::iterator it;
int p[N],inv[P+5],cnt[N<<1],b[N],ans[N],rt[N],vis[N],sum[N][165],a[N];
int m,lim,n,now=1,S,Q,cc,L=155,mx,l,r;
struct query{
	int l,r,id;
	inline bool operator <(const query &b)const{return rt[l]==rt[b.l]?rt[l]&1?r<b.r:r>b.r:l<b.l;}
}q[N];
void init(int n){
	fp(i,2,n){
		if(!vis[i])p[++m]=i,mp[i]=m;
		for(R int j=1;j<=m&&i*p[j]<=n;++j){
			vis[i*p[j]]=1;
			if(i%p[j]==0)break;
		}
	}
}
inline void ins(R int x,R int i,R int j){i<=L?(sum[x][i]+=j,0):(v[x].push_back(node(i,j)),0);}
void solve(int x,int id){
	for(int i=1;i<=lim&&1ll*p[i]*p[i]<=x;++i)if(x%p[i]==0){
		cc=0;while(x%p[i]==0)x/=p[i],++cc;
		ins(id,i,cc);
	}if(x!=1){
		it=mp.find(x);
		if(it==mp.end())p[++m]=x,mp[x]=m,x=m;
		else x=it->second;
		ins(id,x,1);
	}
}
void add(int id){
	go(id)now=1ll*now*inv[cnt[it->v]+1]%P,cnt[it->v]+=it->cnt,now=1ll*now*(cnt[it->v]+1)%P;
}
void del(int id){
	go(id)now=1ll*now*inv[cnt[it->v]+1]%P,cnt[it->v]-=it->cnt,now=1ll*now*(cnt[it->v]+1)%P;
}
int main(){
//	freopen("testdata.in","r",stdin);
//	freopen("testdata.out","w",stdout);
	n=read(),Q=read(),S=sqrt(n);fp(i,1,n)a[i]=read(),cmax(mx,a[i]),rt[i]=(i-1)/S;init(sqrt(mx));
	lim=m;fp(i,1,n){
		fp(j,1,L)sum[i][j]=sum[i-1][j];solve(a[i],i);
	}inv[0]=inv[1]=1;fp(i,2,P-1)inv[i]=1ll*(P-P/i)*inv[P%i]%P;
	fp(i,1,Q)q[i].l=read(),q[i].r=read(),q[i].id=i;
	sort(q+1,q+1+Q);l=1,r=0;
	fp(i,1,Q){
		while(l>q[i].l)add(--l);while(r<q[i].r)add(++r);
		while(l<q[i].l)del(l++);while(r>q[i].r)del(r--);
		ans[q[i].id]=now;fp(j,1,L)ans[q[i].id]=1ll*ans[q[i].id]*(sum[r][j]-sum[l-1][j]+1)%P;
	}fp(i,1,Q)print(ans[i]);return Ot(),0;
}
原文地址:https://www.cnblogs.com/bztMinamoto/p/10116167.html