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);
}
作者:xxy
本文版权归作者和博客园共有,转载请用链接,请勿原文转载,Thanks♪(・ω・)ノ。
原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/14574457.html