zoukankan      html  css  js  c++  java
  • @hdu


    @description@

    给定 A, B, C,求:

    [sum_{i=1}^{A}sum_{j=1}^{B}sum_{k=1}^{C}phi(gcd(i, j^2, k^3))mod 2^{30} ]

    Input
    第一行给定一个整数 T,描述数据组数。
    接下来每组数据包含三个整数 A, B, C,含义如上。
    1 ≤ T ≤ 10, 0 < A, B, C ≤ 10^7

    Output
    对于每组数据,输出答案 mod 2^30。

    Sample Input
    4
    96 93 95
    970 906 893
    92460 95043 54245
    9760979 8053227 7156842
    Sample Output
    1114536
    28070648
    388873924
    623507672

    @solution@

    套路反演一波:

    [ans = sum_{d=1}phi(d)*(sum_{d|p}mu(frac{p}{d})*(sum_{i=1}^{A}[p|i])*(sum_{j=1}^{B}[p|j^2])*(sum_{k=1}^{C}[p|k^3])) ]

    注意到其实 ((sum_{i=1}^{A}[p|i]) = lfloorfrac{A}{p} floor),是比较好求解的,但是另外两项不能直接这么类比着做。
    考虑从唯一分解式的角度去理解。令 (p = prod_{i=0}a_i^{b_i}, j = prod_{i=0}a_i^{c_i})
    如果 (p|j^2),则有 (b_i le 2c_i),于是 (lceilfrac{b_i}{2} ceil le c_i)
    我们令 (f[p] = prod_{i=0}a_i^{lceilfrac{b_i}{2} ceil}),则条件等价转为 (f[p]|j)。类比得到 (g[p]) 的定义以及 (g[p]|k)

    所以答案式变为:

    [ans = sum_{d=1}phi(d)*(sum_{d|p}mu(frac{p}{d})*lfloorfrac{A}{p} floor*lfloorfrac{B}{f[p]} floor*lfloorfrac{C}{g[p]} floor ]

    那么怎么快速求 f[p] 或 g[p] 呢?可以发现 (f[p] = prod_{i=0}f[a_i^{b_i}]),也就是说它是积性函数。
    所以我们就使用线性筛任意积性函数的技巧即可。这里有一个可以参考的连接
    我实现上跟那个博客写得不大一样(不过思想是一致的嗯嗯)。

    然后我们考虑 (sum_{d=1}phi(d)*mu(frac{p}{d})),发现它是两个积性函数的狄利克雷卷积,而众所周知这也是个积性函数。
    然后就可以愉快地再次任意函数线性筛一波。

    最后枚举 p 算答案。时间复杂度 O(n)。

    @accepted code@

    #include<cstdio>
    const int MOD = (1<<30) - 1;
    const int MAXN = int(1E7);
    inline int mul(int a, int b) {return (1LL*a*b)&MOD;}
    int prm[MAXN + 5], pcnt = 0;
    int low[MAXN + 5], f[MAXN + 5], g[MAXN + 5], h[MAXN + 5];
    void sieve() {
    	low[1] = f[1] = g[1] = h[1] = 1;
    	for(int i=2;i<=MAXN;i++) {
    		if( !low[i] ) {
    			low[i] = i, prm[++pcnt] = i;
    			f[i] = i - 2, g[i] = h[i] = i;
    			long long p = 1LL*i*i;
    			for(int j=2;p<=MAXN;p*=i,j++) {
    				low[p] = p;
    				f[p] = p/i/i*(i-1)*(i-1);
    				g[p] = g[p/i];
    				if( (j-1) % 2 == 0 ) g[p] *= i;
    				h[p] = h[p/i];
    				if( (j-1) % 3 == 0 ) h[p] *= i;
    			}
    		}
    		for(int j=1;1LL*i*prm[j]<=MAXN;j++) {
    			if( i % prm[j] == 0 ) {
    				if( i != low[i] ) {
    					low[i*prm[j]] = low[i]*prm[j];
    					f[i*prm[j]] = f[i/low[i]]*f[prm[j]*low[i]];
    					g[i*prm[j]] = g[i/low[i]]*g[prm[j]*low[i]];
    					h[i*prm[j]] = h[i/low[i]]*h[prm[j]*low[i]];
    				}
    				break;
    			}
    			else {
    				low[i*prm[j]] = prm[j];
    				f[i*prm[j]] = f[i]*f[prm[j]];
    				g[i*prm[j]] = g[i]*g[prm[j]];
    				h[i*prm[j]] = h[i]*h[prm[j]];
    			}
    		}
    	}
    }
    void solve() {
    	int A, B, C, ans = 0; scanf("%d%d%d", &A, &B, &C);
    	for(int i=1;i<=A;i++)
    		ans = (1LL*ans + 1LL*mul(mul(f[i], A/i), mul(B/g[i], C/h[i])))&MOD;
    	printf("%d
    ", ans);
    }
    int main() {
    	sieve();
    	int T; scanf("%d", &T);
    	for(int i=1;i<=T;i++) solve();
    }
    

    @details@

    因为是对 2^30 取模,所以可以用位运算加速(虽然我不知道能加到多快,不过应该挺快的)。

  • 相关阅读:
    android 四大组件
    apk 反编译
    通过 PC 远程控制 Android 的应用 -- 可以将手机屏幕投射显示到电脑上
    vmware 装 puppy
    vmware 装 puppy
    js prototype 添加属性对象
    js 百度云搜索框
    js 秒杀
    秒杀的性能和超卖
    [JOI2012春季合宿]Rotate (链表)
  • 原文地址:https://www.cnblogs.com/Tiw-Air-OAO/p/11304614.html
Copyright © 2011-2022 走看看