FZU 2297

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/liufengwei1/article/details/82024725

这题新人队2小时就A了,然后我队中期这题根本不知道怎么办,全机房都会做,于是ljn开始写mod质因数分解一蛤,mod的质因数单独拿出来算,mod<1e9所以最多30个不同的因数,因为2^30>1e9,然后对每一个mod的因数开个mp[j]存数字,cnt[j]存mp[j]在答案中的幂次,对于每一个乘起来的数a[i]我们都把里面mod的质因数给剔到cnt[j]中,然后不是mod的因数就与mod互质,就可以用飞马小定理求逆元了,就直接去算,然后每次都扫一遍cnt[j]得出mod的质因数的乘积,乘以剔除mod的质因数的质因数,然后取mod,就是没事的,这样做比线段树还快一点,考完以后一问他们,全是线段树,线段树的区间合并完美解决%mod=0的情况

#include<cstdio>
#include<cstring>
#include<vector>
#define maxl 100010

using namespace std;

int n;long long mod;
int primes[maxl], vis[maxl];
int mp[100], cnt[100];
long long a[maxl];
vector <long long > p[100];
char s[5];

void getPrime() {
	primes[0] = 0;
	memset(vis, 0, sizeof(vis));
	for (int i = 2; i < maxl; i++) {
		if (!vis[i])
			primes[++primes[0]] = i;
		for (int j = 1; j <= primes[0] && primes[j]*i < maxl; j++) {
			vis[primes[j]*i] = 1;
			if (i % primes[j] == 0)
				break;
		}
	}
}

inline void prework()
{
	scanf("%d%lld",&n,&mod);
	
	mp[0] = 0;
	long long temp = mod;
	for (int i = 1; i <= primes[0] && temp > 1; i++) {
		if (temp%primes[i] == 0) {
			mp[++mp[0]] = primes[i];
			while (temp%primes[i] == 0)
				temp /= primes[i];
		}
	}
	if (temp > 1)
		mp[++mp[0]] = temp;
	memset(cnt, 0, sizeof(cnt));
	for(int i=1;i<=mp[0];i++)
		p[i].clear(),p[i].push_back(1ll);
}

void extgcd(int a, int b, long long &d, long long &x, long long &y){
    if(!b){ d=a; x=1; y=0;}
    else{ extgcd(b,a%b,d,y,x); y-=x*(a/b); }
}

long long inverse(long long a,long long n){
    long long d,x,y;
    extgcd(a,n,d,x,y);
    return d==1?(x+n)%n:-1;
}


inline void mainwork()
{
	int temp, d;
	long long sum, x=1;
	for(int i=1;i<=n;i++)
	{
		scanf("%s",s);
		if(s[0]=='M')
		{
			scanf("%d",&d);
			a[i]=d;
			temp = d;
			sum = 1;
			for (int j = 1; j <= mp[0]; j++) {
				while (temp % mp[j] == 0) {
					cnt[j]++;
					if(p[j].size()<=cnt[j])
					{
						int l=p[j].size();
						p[j].push_back(p[j][l-1]*mp[j]%mod);
					}
					temp /= mp[j];
				}
				sum = (sum * p[j][cnt[j]]) % mod;
			}
			x=(1ll*temp*x)%mod;
			printf("%lld\n",(x*sum) % mod);
		}
		else
		{
			a[i] = 1;
			scanf("%d",&d);
			d = a[d];
			temp = d;
			sum = 1;
			for (int j = 1; j <= mp[0]; j++) {
				while (temp % mp[j] == 0) {
					cnt[j]--;
					temp /= mp[j];
				}
				sum = (sum * p[j][cnt[j]]) % mod;
			}
			x=(x * inverse(temp, mod))%mod;
			printf("%lld\n",(x*sum) % mod);
		}
	}
}

int main()
{
	int t;
	getPrime();
	scanf("%d",&t);
	for(int i=1;i<=t;i++)
	{
		prework();
		mainwork();
	}
	return 0;
}
#include<cstdio>
#include<cstring>
#define maxl 100010

int n,mod;
int a[maxl];
struct node
{
	int l,r,num;
}tree[maxl<<2];
char s[2];

inline void build(int k,int l,int r)
{
	tree[k].l=l;tree[k].r=r;
	if(l==r)
	{
		tree[k].num=1;
		return;
	}
	int mid=(l+r)>>1;
	build(k<<1,l,mid);build(k<<1|1,mid+1,r);
	tree[k].num=1;
}

inline void prework()
{
	scanf("%d%d",&n,&mod);
	build(1,1,n);
}

inline void add(int k,int l,int d)
{
	int mid=(tree[k].l+tree[k].r)>>1;
	if(tree[k].l==tree[k].r)
	{
		tree[k].num=d;
		return;
	}
	if(l<=mid)
		add(k<<1,l,d);
	else
		add(k<<1|1,l,d);
	tree[k].num=1ll*tree[k<<1].num*tree[k<<1|1].num%mod;
}

inline void mainwork()
{
	int d;
	for(int i=1;i<=n;i++)
	{
		scanf("%s%d",s,&d);
		if(s[0]=='M')
			add(1,i,d);
		else
			add(1,d,1);
		printf("%d\n",tree[1].num);
	}
}

int main()
{
	int t;
	scanf("%d",&t);
	for(int i=1;i<=t;i++)
	{
		prework();
		mainwork();
		//print();
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/liufengwei1/article/details/82024725
今日推荐