(atcoder) G - Cubic? 随机数打表,异或

G - Cubic?

大意:给出一个由N个数字组成的序列A,Q次询问一个随机区间 l ,r 将此区间的数连乘起来,问得到的是不是一个立方数

题解: 对每一个数进行质因数分解并存下前i个数乘起来后的每个质因数数量状态(前缀思想),看到大佬都用了一种 随机打表和异或 的操作将这种状态压缩成一个非常大的数,使得查询的复杂度直接降到O(1)

#include<bits/stdc++.h>
#define lowbit(x) ((x)&(-x))
//#define int  long long
using namespace std;
const int N=1e7+10;
int m,n,cnt[N+10];
u64 ran[N+10][3],num=0,h[N+10],mod=1e9+7;
using u64 = unsigned long long;
std::mt19937_64 rng;
signed main()
{
	int i,j,x;

	for(i=1; i<N; i++)
		for(j=0; j<3; j++)
			ran[i][j]=rng();/*对每一个素数所有的数量状态赋一个随机值,打好表*/

    /*num表示乘上前i个数后,所有质因子数量状态的异或结果*/ 
    
	for(i=1; i<N; i++)	num^=ran[i][0];/*刚开始所有质因数的数量状态都为0*/
	h[0]=num;
	scanf("%d%d",&n,&m);
	for(i=1; i<=n; i++)
	{
		scanf("%d",&x);
		for(j=2; j*j<=x; j++)
		{

			if(x%j==0)
			{
				num^=ran[j][cnt[j]];
				/*这里j这个质因数的数量状态改变了,所以先把老的状态擦除,直接异或这个老状态的随机值*/
				while(x%j==0) cnt[j]=(cnt[j]+1)%3,x/=j;
				num^=ran[j][cnt[j]];/*加上新的状态*/
			}
		}
		if(x>1)
		{
			num^=ran[x][cnt[x]];
			cnt[x]=(cnt[x]+1)%3;
			num^=ran[x][cnt[x]];
		}
		h[i]=num;
	}
	while(m--)
	{
		int l,r;
		scanf("%d%d",&l,&r);
		l--;
		if(h[l]==h[r]) printf("Yes\n");
		else printf("No\n");
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值