• 【Luogu P4140】奇数国


    链接:

    题目

    博客园

    题目大意:

    (10^5) 个数,一开始都是 (3),现在有两个操作:

    1. 给定区间 ([l,r]),求它的积的欧拉函数值。

    2. 将第 (x) 个数改为 (y)

    结果对 (19961993) 取模。

    正文:

    本题的难点在于怎么求出 (varphi(product))

    题目中特意提示了:

    这里发行的软妹面额是最小的 (60) 个素数 ((p_1=2,p_2=3,cdots,p_{60}=281)),任何人的财产都只能由这 (60) 个基本面额表示。

    也就说,我们可以通过枚举质因子的那个公式求解:

    [varphi(n)=nprod_{i|n}left(1-frac{1}{p_i} ight) ]

    我们可以通过线段树维护区间积求解出 (product),但是它的质因数呢?

    仍然用线段树维护。因为至多 (60) 个,我们就能用状压了。

    如果先把质数和逆元预处理好,那么求解 (varphi) 值的时间复杂度就是 (O(60)) 了。

    代码:

    const ll mod = 19961993;
    const ll pri[] = {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};
    const ll inv[] = {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};
    
    int m;
    int n = 100000;
    
    struct SegmentTree
    {
    	struct Seg
    	{
    		int l, r;
    		ll val, pri;
    	}t[N << 2];
    	
    	void build (int p, int l, int r)
    	{
    		t[p].l = l, t[p].r = r;
    		if (l == r)
    		{
    			t[p].val = 3, t[p].pri = 2;
    			return ;
    		}
    		int mid = t[p].l + t[p].r >> 1;
    		build (p << 1, l, mid);
    		build (p << 1 | 1, mid + 1, r);
    		t[p].val = t[p << 1].val * t[p << 1 | 1].val % mod;
    		t[p].pri = t[p << 1].pri | t[p << 1 | 1].pri;
    	}
    	void change (int p, int x, ll val, ll P)
    	{
    		if (t[p].l == t[p].r)
    		{
    			t[p].val = val, t[p].pri = P;
    			return ;
    		}
    		int mid = t[p].l + t[p].r >> 1;
    		if (t[p].l <= x && x <= mid) change (p << 1, x, val, P);
    		if (mid + 1 <= x && x <= t[p].r) change (p << 1 | 1, x, val, P);
    		t[p].val = t[p << 1].val * t[p << 1 | 1].val % mod;
    		t[p].pri = t[p << 1].pri | t[p << 1 | 1].pri;
    	}
    	
    	ll query (int p, int l, int r, int opt)
    	{
    		if (l <= t[p].l && t[p].r <= r)
    			return opt? t[p].val: t[p].pri;
    		int mid = t[p].l + t[p].r >> 1;
    		ll ans = opt;
    		if (l <= mid) ans = opt? ans * query(p << 1, l, r, opt) % mod: ans | query(p << 1, l, r, opt);
    		if (mid < r) ans = opt? ans * query(p << 1 | 1, l, r, opt) % mod: ans | query(p << 1 | 1, l, r, opt);
    		return ans;
    	}
    }t;
    
    ll con(ll x)
    {
    	ll tmp = 0;
    	for (ll i = 0; i < 60; i++)
    		if(!(x % pri[i])) tmp |= (1ll << i);
    	return tmp;
    }
    
    int main()
    {
    	scanf ("%d", &m);
    	t.build(1, 1, n);
    	while (m--)
    	{
    		int opt;
    		ll x, y;
    		scanf ("%d%lld%lld", &opt, &x, &y);
    		if (opt == 1) t.change(1, (int)x, y, con(y));
    		else 
    		{
    			ll tmp = t.query(1, (int)x, (int) y, 0);
    			ll ans = t.query(1, (int)x, (int) y, 1);
    			for (ll i = 0; i < 60; i++)
    				if(tmp & (1ll << i)) 
    					ans = (ans * inv[i]) % mod, ans = ans * (pri[i] - 1) % mod;
    			printf("%lld
    ", ans);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    Siri
    ArcSDE和Geodatabase10.1抢先版谍照介绍(3)——ArcToolbox工具和其他功能
    ‘马太’效应
    Linux琐屑下Resin JSP MySQL的布置和设置配备陈设2
    平安防御:分级防御对Linux服务器的攻击
    Linux无法解析域名的处理活动
    Ubuntu Linux Server的用户僻静后果分析
    大概要领确保确保Linux体系中SSH的安适性
    无错版Vsftpd Mysql Pam设置虚拟用户要领
    Redhat Linux AS4下的LAMP与Discuz装置1
  • 原文地址:https://www.cnblogs.com/GJY-JURUO/p/14316453.html
Copyright © 2020-2023  润新知