Gcd & Lcm game 线段树 +位运算操作

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/weixin_43880084/article/details/102636449

LINK

Gcd & Lcm game
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1260 Accepted Submission(s): 298

Problem Description
Tired of playing too much computer games, alpc23 is planning to play a game on numbers. Because plus and subtraction is too easy for this gay, he wants to do some gcd and lcm operations in a number sequence. After playing it a few times, he has found it is also too boring. So he plan to do a more challenge job: he wants to change several numbers in this sequence and also work out the gcd or lcm of all the number in a subsequence of the whole sequence.
To be a friend of this gay, you have been invented by him to play this interesting game with him. Of course, you need to work out the answers faster than him to get a free lunch, He he…

Input
There are multiple test cases.
For each test case.The first line is the length of sequence n, and the number of queries q. (1<=n, q<=100000) The second line has n numbers, they are the initial n numbers of the sequence a1,a2, …,an,
From the third line to the q+2 line are the description of the q operations. They are the one of the two forms:
L k1 k2 p; you need to work out the value after mod p of lcm of the subsequence from k1 to k2, inclusive. (1<=k1<=k2<=n)
G k1 k2 p; you need to work out the value after mod p of gcd of the subsequence from k1 to k2, inclusive. (1<=k1<=k2<=n)
C k v; the k-th number of the sequence has been changed to v.
You can assume that all the numbers before and after the replacement are positive and no larger than 100.

Output
For each of the first or second operation, you need to output the answer in each line.

Sample Input

6 4
1 2 4 5 6 3
L 2 5 17
G 4 6 4
C 4 9
G 4 6 4

Sample Output

9
1
3

Source
2009 Multi-University Training Contest 17 - Host by NUDT

Recommend
lcy | We have carefully selected several similar problems for you: 3078 3070 3072 3073 3074
这种题目没题解完全没得想法啊

  • 采用素数分解的方法存储数据 超级细致啊
  • 0x70000000->0111 0000 0000 0000 0000 0000 0000 0000 用那三个1 的部分存储2 的次数
  • 代码还是好懂的吧
    亲生的代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=100010;
int n,m;
int prime[]={2, 3, 5, 7, 11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97};
int pos[]={28,25,23,21,20,19,18,17,16,15,14,13,12,11,10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0};
//100内的质素分解 2 的最高次数为6 存3 位 0000 0110 0001 0010 0100...
// 3最多出现4次存三位 
// 同理5 的最高次数为2  存两位 之后的质数都之多只可能出现一个也就是只用存一位了
int Max(int x,int y) //处理lcm
{
	return max(x&0x70000000, y&0x70000000) | max(x&0x0e000000, y&0x0e000000) | max(x&0x01800000, y&0x01800000) | max(x&0x00600000, y&0x00600000) | ((x&0x001fffff)|(y&0x001fffff));
} 
int Min(int x,int y) //处理gcd
{
	return min(x&0x70000000, y&0x70000000) | min(x&0x0e000000, y&0x0e000000) | min(x&0x01800000, y&0x01800000) | min(x&0x00600000, y&0x00600000) | ((x&0x001fffff)&(y&0x001fffff));

} 
inline int  ch(int x)//储存数据
{
	int y=0;
	for(int i=0;i<25&&x>1;i++)
	{
		int cnt=0;
		while(x%prime[i]==0)
		{
			x/=prime[i];
			cnt++;
		}
		y|=cnt<<pos[i];
	}return y;
}
int a[]={1,2,4,8,16,32,64};//2的几次
int b[]={1,3,9,27,81};
int c[]={1,5,25};
int d[]={1,7,49};
inline int deal(int x,int p)
{
	int  y=1;
	int k=x>>pos[0];//这个数的因数中2 出现了几次 
	x^=k<<pos[0];//消除x中的2 的部分
    y=(y*a[k])%p;
	k=x>>pos[1];x^=k<<pos[1];
	y=(y*b[k])%p;
	k=x>>pos[2];x^=k<<pos[2];
	y=(y*c[k])%p;
	k=x>>pos[3];y=(y*d[k])%p;x^=k<<pos[3];//这里不消除7的部分也可以的
	for(int i=4;i<25;i++)
	{
	if(x&(1<<pos[i])) y=(y*prime[i])%p;	
	}return y%p;
}
struct node
{
	int l,r,gcd,lcm;
}tr[N<<2];
int h[N];
void up(int rt)
{
	tr[rt].gcd=Min(tr[rt<<1].gcd ,tr[rt<<1|1].gcd );
	tr[rt].lcm=Max(tr[rt<<1].lcm ,tr[rt<<1|1].lcm );
}
void build(int rt,int l,int r)
{
	tr[rt].l=l;tr[rt].r=r;tr[rt].gcd =0x7fffffff;tr[rt].lcm=0;
	if(l==r)
	{
		tr[rt].gcd =tr[rt].lcm=ch(h[l]);return ;
	}
	int mid=(l+r)>>1;
	build(rt<<1,l,mid);
	build(rt<<1|1,mid+1,r);
	up(rt);
}
void update(int rt,int x,int v)
{
	int l=tr[rt].l,r=tr[rt].r;
	if(l==r)
	{
		tr[rt].gcd =tr[rt].lcm=ch(v);
		return ;
	}
	int mid=(l+r)>>1;
	if(x<=mid) update(rt<<1,x,v);
	else update(rt<<1|1,x,v);
	up(rt);
}
int getgcd(int rt,int L,int R )
{
	int l=tr[rt].l,r=tr[rt].r; 
	if(l>=L&&R>=r) return tr[rt].gcd;
	int mid=(l+r)>>1;
	int minn=0x7fffffff;
	if(L<=mid) minn=Min(minn,getgcd(rt<<1,L,R));
	if(R>mid) minn=Min(minn,getgcd(rt<<1|1,L,R));
	return minn;
}
int getlcm(int rt,int L,int R )
{
	int l=tr[rt].l,r=tr[rt].r; 
	if(l>=L&&R>=r) return tr[rt].lcm;
	int mid=(l+r)>>1;int maxx=0;
	if(L<=mid) maxx=Max(maxx,getlcm(rt<<1,L,R));
	if(R>mid) maxx=Max(maxx,getlcm(rt<<1|1,L,R));
	return maxx;
}
int main()
{
	while(~scanf("%d%d",&n,&m))
	{
		for(int i=1;i<=n;i++)
		{
			scanf("%d",&h[i]);
		}build(1,1,n);
		while(m--)
		{
		char s[3];scanf("%s",s);int x,y,p;
		if(s[0]=='C')
		{
			scanf("%d%d",&x,&y);
			update(1,x,y);
		}
		if(s[0]=='G')
		{
			scanf("%d%d%d",&x,&y,&p);
			printf("%d\n",deal(getgcd(1,x,y),p));
		}	
		if(s[0]=='L')
		{
			scanf("%d%d%d",&x,&y,&p);
			printf("%d\n",deal(getlcm(1,x,y),p));
		}
		}
	}
}

猜你喜欢

转载自blog.csdn.net/weixin_43880084/article/details/102636449