• AT2249 ニワンゴくんの約数


    链接:https://www.luogu.com.cn/problem/AT2249
    题意:给定一个序列,每次查询一个区间乘积的约数个数

    AtCoder的题还是比较nb的啊

    显然考虑分解质因数

    然后又很自然地想到根号分治一下

    小于(sqrt{n})的素数可以用前缀和解决

    大于(sqrt{n})的素数可以用莫队解决

    就完了。。

    #include<bits/stdc++.h>
    #define M 80
    #define N 120000
    #define eps 1e-7
    #define inf 1e9+7
    #define db double
    #define ll long long
    #define ldb long double
    #define ull unsigned long long
    using namespace std;
    inline int read()
    {
    	char ch=0;
    	int x=0,flag=1;
    	while(!isdigit(ch)){ch=getchar();if(ch=='-')flag=-1;}
    	while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0',ch=getchar();}
    	return x*flag;
    }
    const int mo=1e9+7;
    struct query{int x,l,r;}p[N];
    bool is_prime[N];
    int a[N],f[N],u[N],d[N],cnt[N],bel[N],Ans[N],prime[N],s[M][N];
    bool cmp(query a,query b)
    {
    	if(bel[a.l]!=bel[b.l])return bel[a.l]<bel[b.l];
    	else return a.r<b.r;
    }
    int ksm(int x,int k)
    {
    	int ans=1;
    	while(k)
    	{
    		if(k&1)ans=1ll*ans*x%mo;
    		k>>=1;x=1ll*x*x%mo;
    	}
    	return ans;
    }
    int inv(int x){return ksm((x%mo+mo)%mo,mo-2);}
    int main()
    {
    	int n=read(),q=read(),sz=max(sqrt(n),1.0),m=0,num=0;
    	for(int i=1;i<=n;i++)a[i]=read(),m=max(m,a[i]),bel[i]=(i-1)/sz+1;
    	for(int i=1;i<=q;i++)p[i].x=i,p[i].l=read(),p[i].r=read();
    	sort(p+1,p+q+1,cmp);
    	memset(is_prime,true,sizeof(is_prime));
    	is_prime[0]=is_prime[1]=false;
    	for(int i=2;i<=m;i++)
    	{
    		if(is_prime[i])prime[++num]=i;
    		for(int j=1;j<=num;j++)
    		{
    			int x=i*prime[j];
    			if(x>m)break;
    			is_prime[x]=false;
    			if(i%prime[j]==0)break; 
    		}
    	}
    	m=max(sqrt(m),1.0); 
    	int len=1;
    	while(prime[len+1]<=m)len++;
    	for(int i=1;i<=n;i++)
    	{
    		int x=a[i];
    		for(int k=1;k<=len;k++)
    		{
    			while(x%prime[k]==0)x/=prime[k],s[k][i]++;
    			s[k][i]+=s[k][i-1];
    		}
    		f[i]=x;
    	}
    	for(int i=1;i<=n+1;i++)u[i]=1ll*(i+1)*inv(i)%mo,d[i]=1ll*(i-1)*inv(i)%mo; 
    	int L=1,R=1,ans;
    	if(f[1]!=1)ans=2;else ans=1;
    	cnt[f[1]]++;
    	for(int i=1;i<=q;i++)
    	{
    		int id=p[i].x,l=p[i].l,r=p[i].r;
    		while(L>l)
    		{
    			L--;
    			int x=f[L];
    			if(x!=1)ans=1ll*ans*u[cnt[x]+1]%mo;
    			cnt[x]++;
    		}
    		while(R<r)
    		{
    			R++;
    			int x=f[R];
    			if(x!=1)ans=1ll*ans*u[cnt[x]+1]%mo;
    			cnt[x]++;
    		}
    		while(L<l)
    		{
    			int x=f[L];
    			if(x!=1)ans=1ll*ans*d[cnt[x]+1]%mo;
    			cnt[x]--;
    			L++;
    		}
    		while(R>r)
    		{
    			int x=f[R];
    			if(x!=1)ans=1ll*ans*d[cnt[x]+1]%mo;
    			cnt[x]--;
    			R--;
    		}
    		Ans[id]=ans;
    		for(int k=1;k<=len;k++)Ans[id]=1ll*Ans[id]*(s[k][r]-s[k][l-1]+1)%mo;
    	}
    	for(int i=1;i<=q;i++)printf("%d
    ",(Ans[i]%mo+mo)%mo);
    	return 0;
    }
    
  • 相关阅读:
    C# 正则表达式
    C# 预处理命令
    C# System.Collections
    C#文件流 System.IO和对文件的读写操作
    c# 网站发布
    C# 数据库
    c# 数据存储过程 存储函数
    insert 插入
    SVN远程管理
    【Win】印象笔记快捷键
  • 原文地址:https://www.cnblogs.com/Creed-qwq/p/13501941.html
Copyright © 2020-2023  润新知