奇数国

奇数国 ⁡ \operatorname{奇数国}

题目链接: luogu P4140 ⁡ \operatorname{luogu\ P4140} luogu P4140

题目

在一片美丽的大陆上有 100   000 100\,000 100000 个国家,记为 1 1 1 100   000 100\,000 100000 。这里经济发达,有数不尽的账房,并且每个国家有一个银行。

某大公司的领袖在这 100   000 100\,000 100000 个银行开户时都存了 3 3 3 大洋,他惜财如命,因此会不时地派小弟 GFS 清点一些银行的存款或者让 GFS 改变某个银行的存款。

该村子在财产上的求和运算等同于我们的乘法运算,也就是说领袖开户时的存款总和为 3 100000 3^{100000} 3100000 。这里发行的软妹面额是最小的 60 60 60 个素数( p 1 = 2 , p 2 = 3 , … , p 60 = 281 p_1=2,p_2=3,\ldots, p_{60}=281 p1=2,p2=3,,p60=281 ),任何人的财产都只能由这 60 60 60 个基本面额表示,即设某个人的财产为 f o r t u n e fortune fortune (正整数),则 f o r t u n e = p 1 k 1 × p 2 k 2 × … p 60 k 60 fortune=p_1^{k_1} \times p_2^{k_2} \times \ldots p_{60}^{k_{60}} fortune=p1k1×p2k2×p60k60

领袖习惯将一段编号连续的银行里的存款拿到一个账房去清点,为了避免 GFS 串通账房叛变,所以他不会每次都选择同一个账房。GFS 跟随领袖多年已经摸清了门路,知道领袖选择账房的方式。如果领袖选择清点编号在 [ a , b ] [a,b] [a,b] 内的银行财产,他会先对 [ a , b ] [a,b] [a,b] 的财产求和(记为 p r o d u c t product product ),然后在编号属于 [ 1 , p r o d u c t ] [1,product] [1,product] 的账房中选择一个去清点存款,检验自己计算是否正确同时也检验账房与 GFS 是否有勾结。GFS 发现如果某个账房的编号 n u m b e r number number p r o d u c t product product 相冲,领袖绝对不会选择这个账房。

怎样才算与 p r o d u c t product product 不相冲呢?若存在整数 x , y x,y x,y 使得 n u m b e r × x + p r o d u c t × y = 1 number \times x+product \times y=1 number×x+product×y=1 ,那么我们称 n u m b e r number number p r o d u c t product product 不相冲,即该账房有可能被领袖相中。当领袖又赚大钱了的时候,他会在某个银行改变存款,这样一来相同区间的银行在不同的时候算出来的 p r o d u c t product product 可能是不一样的,而且领袖不会在某个银行的存款总数超过 1 0 6 10^6 106

现在 GFS 预先知道了领袖的清点存款与变动存款的计划,想请你告诉他,每次清点存款时领袖有多少个账房可以供他选择,当然这个值可能非常大,GFS 只想知道对 19   961   993 19\,961\,993 19961993 取模后的答案。

输入

第一行一个整数 x x x 表示领袖清点和变动存款的总次数。

接下来 x x x 行,每行 3 3 3 个整数 a i , b i , c i a_i,b_i,c_i ai,bi,ci a i a_i ai 0 0 0 时表示该条记录是清点计划,领袖会清点 b i b_i bi c i c_i ci 的银行存款,你需要对该条记录计算出 GFS 想要的答案。 a i a_i ai 1 1 1 时表示该条记录是存款变动,你要把银行 b i b_i bi 的存款改为 c i c_i ci ,不需要对该记录进行计算。

输出

对于每个询问,输出一行一个整数表示答案。

样例输入

6
0 1 3
1 1 5
0 1 3
1 1 7
0 1 3
0 2 3

样例输出

18
24
36
6

样例解释

初始化每个国家存款都为 3 3 3
1 1 1 3 3 3 p r o d u c t product product 27 27 27 [ 1 , 27 ] [1,27] [1,27] 27 27 27 不相冲的有 18 18 18 个数;
1 1 1 的存款变为 5 5 5
1 1 1 3 3 3 p r o d u c t product product 45 45 45 [ 1 , 45 ] [1,45] [1,45] 45 45 45 不相冲的有 24 24 24 个数;
1 1 1 的存款变为 7 7 7
1 1 1 3 3 3 p r o d u c t product product 63 63 63 [ 1 , 63 ] [1,63] [1,63] 63 63 63 不相冲的有 36 36 36 个数;
2 2 2 3 3 3 p r o d u c t product product 9 9 9 [ 1 , 9 ] [1,9] [1,9] 9 9 9 不相冲的有 6 6 6 个数。

数据范围

所有数据均满足: x ≥ 1 x \geq 1 x1 c i − b i ≥ 0 c_i -b_i \geq 0 cibi0

扫描二维码关注公众号,回复: 11724308 查看本文章
子任务编号 分值 x ≤ x\leq x c i − b i ≤ c_i-b_i\leq cibi 特殊性质
1 1 1 20 20 20 1 0 4 10^4 104 100 100 100
2 2 2 30 30 30 5 ∗ 1 0 4 5*10^4 5104 1 0 4 10^4 104
3 3 3 50 50 50 1 0 5 10^5 105 1 0 5 10^5 105

特殊性质指:所有 p r o d u c t ≤ 1 0 18 product \leq 10^{18} product1018

思路

这道题就是数学题,不过要用线段树来维护。

我们可以发现,其实这道题要求的就是区间的积的欧拉函数。
众所周知(但是我不知 ) ,欧拉函数可以这么求:
ϕ ( n ) = n ( 1 − 1 p 1 ) ( 1 − 1 p 2 ) . . . ( 1 − 1 p i ) ϕ(n)=n(1− \frac{1}{p_1})(1− \frac{1}{p_2})...(1− \frac{1}{p_i}) ϕ(n)=n(1p11)(1p21)...(1pi1)
p i p_i pi 表示 n n n 的每个质因子)

因为题目说 n n n 只由前六十个素数组成,那这种方法就是可行的。
这六十个素数和他们的逆元可以预处理,可以求出,也可以直接打表,反正我这里打表了。

至于会修改点的值和求区间的积,我们就可以发现其实完全可以用线段树来求。那我们就用线段树来维护区间的积和这个积的质因子。(用二进制来存, 2 60 2^{60} 260 可以用 l o n g   l o n g long\ long long long 存下)

那基本就这样了。

代码

#include<cstdio>
#define ll long long
#define mo 19961993

using namespace std;

//预处理(打表)出素数和其逆元
ll su[] = {
    
    0, 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, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281};
ll ni[] = {
    
    0, 9980997, 6653998, 11977196, 8555140, 5444180, 1535538, 10568114, 14708837, 3471651, 11701858, 17386252, 1618540, 16066970, 2321162, 18263100, 16948862, 12518538, 15380552, 10725847, 1686929, 13399146, 17182475, 12025297, 15924736, 13582387, 395287, 6395590, 15857658, 16299242, 6359573, 3300802, 18742940, 6702567, 10914471, 16210746, 11765678, 5340151, 18247466, 7769638, 8077107, 11932588, 6506948, 1985748, 6619521, 5877135, 4413707, 9744480, 10115270, 14597757, 16475182, 18334191, 5011379, 18885205, 7555336, 621385, 11309266, 12170137, 12006660, 18304499, 11153142};
bool susu[301];

int n, x, y, z;
ll ans, gtree, gmi;
struct node {
    
    
	ll sum, mi;
}tree[400001];

int ksm(int x, int y) {
    
    
	if (!y) return 1;
	int re = 1;
	for (; y; y >>= 1) {
    
    
		if (y & 1) re = (re * x) % mo;
		x = (x * x) % mo;
	}
	return re;
}

void build(int l, int r, int now) {
    
    //建树
	if (l == r) {
    
    
		tree[now].sum = 3;
		tree[now].mi = 2;
		return ;
	}
	
	int mid = (l + r) / 2;
	build(l, mid, now * 2);
	build(mid + 1, r, now * 2 + 1);
	
	tree[now].sum = (tree[now * 2].sum * tree[now * 2 + 1].sum) % mo;
	tree[now].mi = 2;
}

void change(int now, int l, int r, int x, int num) {
    
    //单点修改值
	if (l == r) {
    
    
		tree[now].sum = num;
		tree[now].mi = 0;
		for (int i = 1; i <= 60; i++)
			if ((num % su[i]) == 0) tree[now].mi |= 1ll << (i - 1);
		return ;
	}
	
	int mid = (l + r) / 2;
	if (x <= mid) change(now * 2, l, mid, x, num);
		else change(now * 2 + 1, mid + 1, r, x, num);
	
	tree[now].sum = (tree[now * 2].sum * tree[now * 2 + 1].sum) % mo;
	tree[now].mi = tree[now * 2].mi | tree[now * 2 + 1].mi;
}

void getans(int now, int l, int r, int al, int ar) {
    
    //区间查询
	if (l >= al && r <= ar) {
    
    
		gtree = (gtree * tree[now].sum) % mo;
		gmi |= tree[now].mi;
		return ;
	}
	
	int mid = (l + r) / 2;
	if (al <= mid) getans(now * 2, l, mid, al, ar);
	if (mid < ar) getans(now * 2 + 1, mid + 1, r, al, ar);
}

int main() {
    
    
	build(1, 100000, 1);//建树
	
	scanf("%d", &n);//读入
	for (int i = 1; i <= n; i++) {
    
    
		scanf("%d %d %d", &z, &x, &y);//读入
		if (z) change(1, 1, 100000, x, y);//单点改权值
			else {
    
    
				gtree = 1;
				gmi = 0;
				getans(1, 1, 100000, x, y);//区间查询
				
				ans = gtree;
				for (int i = 1; i <= 60; i++)
					if ((1ll << (i - 1)) & gmi) {
    
    //找到里面有的素数
						ans = (ans * (su[i] - 1)) % mo;
						ans = (ans * ni[i]) % mo;
					}
				
				printf("%lld\n", ans);//输出
			}
	}
	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43346722/article/details/108109769
今日推荐