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);
}
posted @ 2021-03-24 18:08  TRTTG  阅读(59)  评论(0编辑  收藏  举报