zoukankan      html  css  js  c++  java
  • [BZOJ4026]dC Loves Number Theory

    [BZOJ4026]dC Loves Number Theory

    试题描述

    dC 在秒了BZOJ 上所有的数论题后,感觉萌萌哒,想出了这么一道水题,来拯救日益枯竭的水题资源。 
    给定一个长度为 n的正整数序列A,有q次询问,每次询问一段区间内所有元素乘积的φ(φ(n)代表1~n 中与n互质的数的个数) 。由于答案可能很大,所以请对答案 mod (10^6 + 777)。 (本题强制在线,所有询问操作的l,r都需要 xor上一次询问的答案 lastans,初始时,lastans = 0) 

    输入

    第一行,两个正整数,N,Q,表示序列的长度和询问的个数。 

    第二行有N 个正整数,第i个表示Ai. 
    下面Q行,每行两个正整数,l r,表示询问[l ^ lastans,r ^ lastans]内所有元素乘积的φ

    输出

    Q行,对于每个询问输出一个整数。 

    输入示例

    5 10
    3 7 10 10 5
    3 4
    42 44
    241 242
    14 9
    1201 1201
    0 6
    245 245
    7 7
    6 1
    1203 1203

    输出示例

    40
    240
    12
    1200
    2
    240
    4
    4
    1200
    4

    数据规模及约定

    1 <= N <= 50000 

    1 <= Q <= 100000 

    1 <= Ai <= 10^6 
    题解
    把原序列中每个数 Ai 拆成不超过 logAi 个质因数,然后思路基本和上一题一样,只不过维护的东西换了(提示:想想怎么求 φ)。
    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <stack>
    #include <vector>
    #include <queue>
    #include <cstring>
    #include <string>
    #include <map>
    #include <set>
    using namespace std;
    
    const int BufferSize = 1 << 16;
    char buffer[BufferSize], *Head, *Tail;
    inline char Getchar() {
    	if(Head == Tail) {
    		int l = fread(buffer, 1, BufferSize, stdin);
    		Tail = (Head = buffer) + l;
    	}
    	return *Head++;
    }
    int read() {
    	int x = 0, f = 1; char c = Getchar();
    	while(!isdigit(c)){ if(c == '-') f = -1; c = Getchar(); }
    	while(isdigit(c)){ x = x * 10 + c - '0'; c = Getchar(); }
    	return x * f;
    }
    
    #define maxn 800010
    #define maxnode 12800010
    #define maxp 1000010
    #define maxlog 20
    #define MOD 1000777
    #define LL long long
    
    int A[maxn], nn, pos[maxn], lstp[maxp], Mulsum[maxn], inv[MOD];
    void gcd(int a, int b, int& x, int& y) {
    	if(!b){ x = 1; y = 0; return ; }
    	gcd(b, a % b, y, x); y -= a / b * x;
    	return ;
    }
    int Inv(int a) {
    	int x, y;
    	gcd(a, MOD, x, y);
    	return (x % MOD + MOD) % MOD;
    }
    int prime[maxp], cnt, val[maxp], nxt[maxp], tval[maxlog];
    bool vis[maxp];
    void prime_table() {
    	for(int i = 2; i <= maxp - 10; i++) {
    		if(!vis[i]) prime[++cnt] = i, val[i] = prime[cnt], nxt[i] = i;
    		for(int j = 1; j <= cnt && i * prime[j] <= maxp - 10; j++) {
    			vis[i*prime[j]] = 1;
    			val[i*prime[j]] = prime[j]; nxt[i*prime[j]] = i;
    			if(i % prime[j] == 0) break;
    		}
    	}
    	return ;
    }
    
    int ToT, rt[maxn], Mul[maxnode], lc[maxnode], rc[maxnode];
    void update(int& y, int x, int l, int r, int p, int v) {
    	if(v > 1) Mul[y = ++ToT] = ((LL)Mul[x] * (v - 1) % MOD) * inv[v] % MOD;
    	else Mul[y = ++ToT] = Mul[x];
    //	printf("%d %d %d: %d(%d %d %d)
    ", y, l, r, Mul[y], x, v, inv[v]);
    	if(l == r) return ;
    	int mid = l + r >> 1; lc[y] = lc[x]; rc[y] = rc[x];
    	if(p <= mid) update(lc[y], lc[x], l, mid, p, v);
    	else update(rc[y], rc[x], mid + 1, r, p, v);
    	return ;
    }
    LL query(int o, int l, int r, int qr) {
    	if(!o) return 1;
    	if(r <= qr) return Mul[o];
    	int mid = l + r >> 1;
    	LL ans = query(lc[o], l, mid, qr);
    	if(qr > mid) (ans *= query(rc[o], mid + 1, r, qr)) %= MOD;
    	return ans;
    }
    
    int ANS[maxn], len;
    char Out[maxn];
    int main() {
    //	freopen("data.in", "r", stdin);
    //	freopen("data.out", "w", stdout);
    	for(int i = 0; i < MOD; i++) inv[i] = Inv(i);
    	prime_table();
    	int n = read(), q = read();
    	Mulsum[0] = 1;
    	for(int i = 1; i <= n; i++) {
    		int tmp = read();
    		Mulsum[i] = (LL)Mulsum[i-1] * tmp % MOD;
    		pos[i] = nn + 1;
    		if(tmp == 1) A[++nn] = 1;
    		else {
    			int j = tmp, tc = 0;
    			for(; nxt[j] != j; j = nxt[j]) tval[++tc] = val[j];
    			tval[++tc] = val[j];
    			tc = unique(tval + 1, tval + tc + 1) - tval - 1;
    			for(j = 1; j <= tc; j++) A[++nn] = tval[j];
    		}
    	}
    	pos[n+1] = nn + 1;
    	n = nn; Mul[0] = 1;
    	for(int i = 1; i <= n; i++) {
    		update(rt[i], rt[i-1], 0, n, lstp[A[i]], A[i]);
    		lstp[A[i]] = i;
    	}
    	/*printf("n: %d
    ", n);
    	for(int i = 1; i <= n; i++) printf("%d%c", A[i], i < n ? ' ' : '
    ');
    	for(int i = 1; i <= n; i++) printf("%d ", pos[i]); putchar('
    ');*/
    	int lst = 0;
    	for(int i = 1; i <= q; i++) {
    		int ql = read() ^ lst, qr = read() ^ lst;
    		int l = pos[ql], r = pos[qr+1] - 1;
    		int Multi = (LL)Mulsum[qr] * inv[Mulsum[ql-1]] % MOD;
    //		printf("Multi: %d %d %d %d %d
    ", Multi, rt[r], rt[l-1], query(rt[r], 0, n, l - 1), query(rt[l-1], 0, n, l - 1));
    		lst = (query(rt[r], 0, n, l - 1) * inv[query(rt[l-1],0,n,l-1)] % MOD) * Multi % MOD;
    		ANS[i] = lst;
    //		lst = 0;
    	}
    	int num[10], cntn;
    	for(int i = 1; i <= q; i++) {
    		int tmp = ANS[i];
    //		printf("%d
    ", ANS[i]);
    		if(!tmp) Out[len++] = '0';
    		cntn = 0;
    		while(tmp) num[++cntn] = tmp % 10, tmp /= 10;
    		for(int j = cntn; j; j--) Out[len++] = num[j] + '0';
    		if(i < q) Out[len++] = '
    '; else Out[len++] = '';
    	}
    	puts(Out);
    	
    	return 0;
    }
    

    不知为何把求逆元的部分都改成 long long 交到大视野上就 T 飞,害得我差点调了一年。。。

    2017-4-21

    上面代码又臭又长,我补一个好看点的。。。

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cctype>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    
    int read() {
    	int x = 0, f = 1; char c = getchar();
    	while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
    	while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
    	return x * f;
    }
    
    #define maxn 50010
    #define maxnum 1000010
    #define maxnode 20000010
    #define MOD 1000777
    #define LL long long
    
    int n, Sum[maxn], lst[maxnum], rt[maxn];
    
    void gcd(LL a, LL b, LL& x, LL& y) {
    	if(!b){ x = 1; y = 0; return ; }
    	gcd(b, a % b, y, x); y -= a / b * x;
    	return ;
    }
    int Inv(int a) {
    	LL x, y;
    	gcd(a, MOD, x, y);
    	return (x % MOD + MOD) % MOD;
    }
    
    int ToT, Fac[maxnode], lc[maxnode], rc[maxnode];
    void update(int& y, int x, int l, int r, int p, int v) {
    	Fac[y = ++ToT] = (LL)Fac[x] * v % MOD;
    	if(l == r) return ;
    	int mid = l + r >> 1; lc[y] = lc[x]; rc[y] = rc[x];
    	if(p <= mid) update(lc[y], lc[x], l, mid, p, v);
    	else update(rc[y], rc[x], mid + 1, r, p, v);
    	return ;
    }
    int query(int o, int l, int r, int qr) {
    	if(r <= qr) return Fac[o];
    	int mid = l + r >> 1, ans = query(lc[o], l, mid, qr);
    	if(qr > mid) ans = (LL)ans * query(rc[o], mid + 1, r, qr) % MOD;
    	return ans;
    }
    
    int main() {
    	n = read(); int q = read();
    	Fac[0] = Sum[0] = 1;
    	for(int i = 1; i <= n; i++) {
    		int A = read();
    		Sum[i] = (LL)Sum[i-1] * A % MOD;
    		int m = sqrt(A + .5);
    		rt[i] = rt[i-1];
    		for(int x = 2; x <= m; x++) if(A % x == 0) {
    			update(rt[i], rt[i], 0, n, lst[x], (LL)(x - 1) * Inv(x) % MOD); lst[x] = i;
    			while(A % x == 0) A /= x;
    		}
    		if(A > 1) update(rt[i], rt[i], 0, n, lst[A], (LL)(A - 1) * Inv(A) % MOD), lst[A] = i;
    	}
    	
    	int lstans = 0;
    	while(q--) {
    		int l = read() ^ lstans, r = read() ^ lstans;
    		printf("%d
    ", lstans = (LL)Sum[r] * Inv(Sum[l-1]) % MOD * query(rt[r], 0, n, l - 1) % MOD * Inv(query(rt[l-1], 0, n, l - 1)) % MOD);
    	}
    	
    	return 0;
    }
    
  • 相关阅读:
    CentOS7 安装 RabbitMQ
    测试工程师 - 要了解的技能总结
    STF 连接其它操作系统上的安卓设备实操介绍【转】
    adb -a server nodaemon,设备一直显示 offline,而 adb devices 一直显示 device【已解决】
    Mac 之 STF 搭建(淘宝源安装)
    无损压缩图片
    jenkins 之 Android 打包及上传至蒲公英
    JoinPoint
    元数据库 information_schema.tables
    @RestControllerAdvice全局异常统一处理
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/6358429.html
Copyright © 2011-2022 走看看