P4588 [TJOI2018]数学计算

传送门:P4588

题目描述

小豆现在有一个数 x,初始值为 1。小豆有 Q 次操作,操作有两种类型:

1 m:将 x 变为x*m,并输出x mod M

2 pos:将 x 变为 x 除以第 pos 次操作所乘的数(保证第 pos 次操作一定为类型 1,对于每一个类型 1 的操作至多会被除一次),并输出 x mod M。

输入格式

一共有 t 组输入。

对于每一组输入,第一行是两个数字 Q,M。

接下来 Q 行,每一行为操作类型 op,操作编号或所乘的数字 m(保证所有的输入都是合法的)。

输出格式

对于每一个操作,输出一行,包含操作执行后的 x mod M 的值。

输入输出样例

输入 #1

1
10 1000000000
1 2
2 1
1 2
1 10
2 3
2 4
1 6
1 7
1 12
2 7

输出 #1

2
1
2
20
10
1
6
42
504
84

说明/提示 

对于 20% 的数据,1≤Q≤500。

对于 100% 的数据,1≤Q≤10^{5},t≤5,M≤10^{9},0<m≤10^{9}

思路

通过题目,一秒看出

线段树!

先建树:

非常简单,注意一下边界

void build(int x,int l,int r){
	L[x]=l;
	R[x]=r;
	prod[x]=1;
	if(l==r){
	    return;
	}
	int mid=(l+r)/2;
	build(x*2,l,mid);
	build(x*2+1,mid+1,r);
}

接着是修改:

非常经典,不过这里需要一个新数组,prod表示区间所有数乘积。

void modify(int x,int p,int v){
	if(L[x]==R[x]){
		prod[x]=v;
		return;
	}
	int mid=(L[x]+R[x])/2;
	if(p<=mid){
	    modify(x*2,p,v);
	}else{
	    modify(x*2+1,p,v);
	}
	prod[x]=1LL*prod[x*2]*prod[x*2+1]%mod;
}

主题代码就是这些,main里非常好写

AC代码如下:

#include<bits/stdc++.h>
using namespace std;
const int MAXN=100009;
int n,mod,a[MAXN],L[MAXN*4],R[MAXN*4],prod[MAXN*4];
//prod: 区间所有数乘积
void build(int x,int l,int r){
	L[x]=l;
	R[x]=r;
	prod[x]=1;
	if(l==r){
	    return;
	}
	int mid=(l+r)/2;
	build(x*2,l,mid);
	build(x*2+1,mid+1,r);
}
void modify(int x,int p,int v){
	if(L[x]==R[x]){
		prod[x]=v;
		return;
	}
	int mid=(L[x]+R[x])/2;
	if(p<=mid){
	    modify(x*2,p,v);
	}else{
	    modify(x*2+1,p,v);
	}
	prod[x]=1LL*prod[x*2]*prod[x*2+1]%mod;
}
int main(){
	int t;
	cin>>t;
	while(t--){
		cin>>n>>mod;
		build(1,1,n);
		for(int i=1;i<=n;i++){
		    int q,m;
			cin>>q>>m;
			if(q==1){
				modify(1,i,m);
				cout<<prod[1]<<endl;
			}else{
				modify(1,m,1);
				cout<<prod[1]<<endl; 
			}
		}
	}
	return 0 ; 
}

-----------------------------------------------------祝大家AC快乐!------------------------------------------------------

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值