牛客网-F-发电(费马小定理+线段树)

链接:https://www.nowcoder.com/acm/contest/136/F
来源:牛客网
 

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

    HA实验是一个生产、提炼“神力水晶”的秘密军事基地,神力水晶可以让机器的工作效率成倍提升。
    HA实验基地有n台发电机,标号为1-n,每台发电机的发电效率为1。
    为了满足基地的用电需求,HtBest会在某台发电机上镶嵌一个等级为i的神力水晶,该发电机的发电效率是镶嵌神力水晶之前的i倍,一个发电机可以同时镶嵌多个神力水晶。
    但是神力水晶有时还有别的用处,HtBest会拆掉某台发电机之前镶嵌上的一个神力水晶(设等级为i),发电机效率降为拆掉神力水晶前的1/i。
    HtBest有时想知道第l到r台发电机的总发电效率为多少。

输入描述:

第一行有2个正整数n,m,分别表示发电机数量和操作数。
接下来m行,每行有3个正整数,x, y, z。
x=1时,HtBest镶嵌为第y台发电机镶嵌了一个等级为z的神力水晶,
x=2时,HtBest为第y台发电机拆掉了一个等级为z的神力水晶,
x=3时,HtBest想知道[y,z]的发电机效率的乘积。

输出描述:

对于每个x=3的操作,输出一行,表示[y,z]的发电机的效率的乘积。
由于输出过大,你需要对输出结果模1000000007(1e9+7)。

示例1

输入

复制

4 4
1 2 3
3 1 4
2 2 3
3 1 4

输出

复制

3
1

说明

操作1之后,每台发电机效率:1 3 1 1
操作3之后,每台发电机效率:1 1 1 1

示例2

输入

复制

4 4
1 2 2
1 2 3
1 3 4
3 1 4

输出

复制

24

说明

操作1之后,每台发电机效率:1 2 1 1
操作2之后,每台发电机效率:1 6 1 1
操作3之后,每台发电机效率:1 6 4 1

备注:

对于100%的测试数据:
1 ≤ n, m ≤ 1000000
1 ≤ 神力水晶等级 ≤ 100000
数据量较大,注意使用更快的输入输出方式。

思路:这题数据范围过大,每一个水晶的能量有可能会很大,因此在移除水晶的时候,需要使用到逆元取模,其余都是线段树模板。

code:

#include<cstdio>

#define N 1000010
#define MOD 1000000007
typedef long long ll;
struct n{
	ll val;
	int left, right;
}Tree[4 * N];

int Elec[N];

void createTree(int root, int l, int r){
	if(l == r){
		Tree[root].val = Elec[l];
		return;
	}
	int mid = (l + r) >> 1;
	createTree(root << 1, l, mid);
	createTree(root << 1 | 1, mid + 1, r);
	Tree[root].val = (Tree[root << 1].val * Tree[root << 1 | 1].val) % MOD;
}

ll search(int root, int ml, int mr, int l, int r){
	if(l > mr || r < ml){
		return 1;
	}
	
	if(l <= ml && r >= mr){
		return Tree[root].val % MOD;
	}
	int mid = (ml + mr) >> 1;
	return (search(root << 1, ml, mid, l, r) * search(root << 1 | 1, mid + 1, mr, l, r)) % MOD;
}

void updateMul(int root, int l, int r, int index, int val){
	if(l == r){
		if(index == l){
			Tree[root].val *= val;
			Tree[root].val %= MOD;
		}
		return;
	}
	int mid = (l + r) >> 1;
	if(index <= mid){
		updateMul(root << 1, l, mid, index, val);
	}else{
		updateMul(root << 1 | 1, mid + 1, r, index, val);
	}
	Tree[root].val = (Tree[root << 1].val * Tree[root << 1 | 1].val) % MOD;
}

ll inverse(int val){
	ll n = MOD - 2;
	ll base = val;
	ll res = 1;
	while(n){
		if(n & 1){
			res = (res * base) % MOD;
		}
		n >>= 1;
		base = (base * base) % MOD;
	}
	return res;
}

void updateDiv(int root, int l, int r, int index, int val){
	if(l == r){
		if(index == l){
			Tree[root].val *= inverse(val);
			Tree[root].val %= MOD;
		}
		return;
	}
	int mid = (l + r) >> 1;
	if(index <= mid){
		updateDiv(root << 1, l, mid, index, val);
	}else{
		updateDiv(root << 1 | 1, mid + 1, r, index, val);
	}
	Tree[root].val = (Tree[root << 1].val * Tree[root << 1 | 1].val) % MOD ;
}

int main(){
	
	int n, m;
	scanf("%d %d", &n, &m);
	for(int i = 1;i <= n;i++){
		Elec[i] = 1;
	}
	createTree(1, 1, n);
	for(int i = 0;i < m;i++){
		int x, y, z;
		scanf("%d %d %d", &x, &y, &z);
		if(x == 1){
			updateMul(1, 1, n, y, z);
		}else if(x == 2){
			updateDiv(1, 1, n, y, z);
		}else if(x == 3){
			ll res = search(1, 1, n, y, z);
			printf("%lld\n", res);
		}
	}
	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/a568283992/article/details/81939916
今日推荐