51nod 1026 矩阵中不重复的元素 V2
将底数质因子分解,假设底数的质因子分解结果为 \(x={p_1}^{k_1}{p_2}^{k_2}...{p_n}^{k_n}\)
令\(g=gcd(k_1,k_2,...k_n)\) , \(e_i=k_i/g\)
则\(x={({p_1}^{e_1}{p_2}^{e_2}...{p_n}^{e_n})}^{g}\)
令\(S={p_1}^{e_1}{p_2}^{e_2}...{p_n}^{e_n}\)
所以\(x^y={({p_1}^{e_1}{p_2}^{e_2}...{p_n}^{e_n})}^{g*y}=S^{g*y}\)
所以对于\(S\)相同的\(x^y\),有多少个不同的 \(g*y\) 就有多少个不同的\(x^y\)
进一步发现,对于不同的\(S\),只需要知道有多少个不同的\(g*y\),与\(S\)本身是多少没有关系。
\(y\)的取值为\([b,b+m)\) , 是固定的
\(g\)最大取19,因为\(2^{19}>1e6\)
用数组\(g[i][j]\)表示 \(g\)取\([i,j]\)时,\(g*y\)的个数
这个可以暴力 \(O(log(a+n)*(m))\) 计算
最后缺的就是对于每个S,它在\(x∈[a,a+n)\)时,g的取值上界和下界
这个对于每个\(x\),计算它对应的\(S\)和\(g\)
正着扫一遍遇到的第一个就是下界
倒着扫一遍遇到的最后一个就是上界
#include<cstdio>
#include<cstring>
using namespace std;
#define N 1000001
#define M 20
int bl[N],num[N],l[N],r[N];
int fir[N],cnt;
int g[M][M];
bool vis[N*M];
int main()
{
int m,n,a,b,id;
scanf("%d%d%d%d",&m,&n,&a,&b);
for(int i=2;i<n+a;++i)
if(!bl[i])
{
id=1;
bl[i]=i;
num[i]=1;
fir[++cnt]=i;
for(long long j=1ll*i*i;j<n+a;j*=i)
{
bl[j]=i;
num[j]=++id;
}
}
int tot;
for(int i=1;i<M;++i)
{
tot=0;
memset(vis,false,sizeof(vis));
for(int j=i;j<M;++j)
{
for(int k=b;k<m+b;++k)
if(!vis[j*k])
{
vis[j*k]=true;
++tot;
}
g[i][j]=tot;
}
}
for(int i=a;i<n+a;++i)
if(!l[bl[i]]) l[bl[i]]=num[i];
for(int i=n+a-1;i>=a;--i)
if(!r[bl[i]]) r[bl[i]]=num[i];
long long ans=0;
for(int i=1;i<=cnt;++i)
ans+=g[l[fir[i]]][r[fir[i]]];
printf("%lld",ans);
}