zoukankan      html  css  js  c++  java
  • hdu 4407 Sum 容斥原理

    题意很简单,就是给你一个数组大小为n的值从1到n,之后有m次操作,要么修改前面的数组中的某一项,要么是输出从x到y(包括边界)中的数与p互质的数的和。由于m很小(m<=1000)故,将修改的部分保存下来之后统计输出时,在判断修改的部分是否与p互质,若是要修改原来的,在修改现在的。

    注意,就是多次修改同一个地方,只记录最后一次。

    对于统计从x到y的与p互质数的和,有结果=数1到y的满足要求的结果-数1到x-1的满足要求的结果。

    而从1开始到n的数中与p互质的数的和的求法,就是个容斥原理的算法。

    剔除p中单个素因子的倍数,加上两个因子的倍数,接着在剔除三个素因子的倍数,直到所有的素因子结束。

    。/**   
     * @Title: HDU4407.java 
     * @Package com.wangzhu.hdu 
     * @Description: TODO
     * @author 王竹
     * @date 2012-9-22 下午7:40:27 
     * @version V1.0   
     *
     */
    package com.wangzhu.hdu;
    
    import java.io.BufferedInputStream;
    import java.util.Arrays;
    import java.util.Scanner;
    
    /**
     * @ClassName: HDU4407
     * @Description: TODO
     * @author 王竹
     * @date 2012-9-22 下午7:40:27
     * 
     */
    public class HDU4407 {
    
        public static void main(String[] args) {
            // System.setIn(new FileInputStream("data.in"));
            Scanner cin = new Scanner(new BufferedInputStream(System.in));
            int t, n, m, cas, x, y, c, p;
            initPrime();
            while (cin.hasNext()) {
                t = cin.nextInt();
                while (t-- > 0) {
                    n = cin.nextInt();
                    m = cin.nextInt();
                    node = new Node[m + 1];
                    lastIndex = new int[MAXN];
                    nodeLen = 0;
                    for (int i = 0; i < m; i++) {
                        cas = cin.nextInt();
                        if (cas == 2) {
                            x = cin.nextInt();
                            c = cin.nextInt();
                            node[nodeLen] = new Node(x, c);
                            lastIndex[x] = nodeLen++;
                        } else {
                            x = cin.nextInt();
                            y = cin.nextInt();
                            p = cin.nextInt();
                            work(x, y, p, n);
    
                        }
                    }
                }
            }
            cin.close();
        }
    
        private final static int MAXN = 400001;
        static int[] lastIndex;
        private final static int VAL = 1000;
        static int[] prime = new int[VAL];
        static boolean[] isPrime = new boolean[VAL];
        static int primeLen;
    
        public static void initPrime() {
            Arrays.fill(isPrime, false);
            primeLen = 0;
            prime[primeLen++] = 2;
            for (int i = 4; i < VAL; i += 2) {
                isPrime[i] = true;
            }
            for (int i = 3; i < VAL; i += 2) {
                if (!isPrime[i]) {
                    prime[primeLen++] = i;
                }
                for (int j = 0; (j < primeLen) && (i * prime[j] < VAL); j++) {
                    isPrime[i * prime[j]] = true;
                    if (i % prime[j] == 0) {
                        break;
                    }
                }
            }
        }
    
        static Node[] node;
        static int nodeLen;
    
        static int[] primeFactor; // 存储素因子
        static int primeFactorLen;
    
        /**
         * 分解数p获得其素因子
         * 
         * @param p
         */
        public static void mkPrimeFactor(int p) {
            primeFactor = new int[VAL];
            int temp = (int) Math.sqrt(1.0 * p);
            primeFactorLen = 0;
            for (int i = 0; (i < primeLen) && (prime[i] <= temp); i++) {
                if (p % prime[i] == 0) {
                    primeFactor[primeFactorLen++] = prime[i];
                    while (p % prime[i] == 0) {
                        p /= prime[i];
                    }
                }
            }
            if (p > 1) {
                primeFactor[primeFactorLen++] = p;
            }
        }
    
        private static void work(int x, int y, int p, int n) {
            mkPrimeFactor(p);
            long res = getSum(y) - getSum(x - 1);
            for (int i = 0; i < nodeLen; i++) {
                if (node[i].x >= x && node[i].x <= y) {
                    // 若是多次修改同一个地方,则只取最后一次
                    if (i != lastIndex[node[i].x]) {
                        continue;
                    }
                    if (isCoPrime(node[i].x, p)) {
                        res -= node[i].x;
                    }
                    if (isCoPrime(node[i].c, p)) {
                        res += node[i].c;
                    }
                }
            }
            System.out.println(res);
        }
    
        private static long getSum(int i) {
            long res = (long) i * (i + 1) / 2;
            res -= dfs(0, i, 1);
            return res;
        }
    
        private static boolean isCoPrime(int c, int p) {
            return gcd(c, p) == 1;
        }
    
        /**
         * 最大公约数
         * 
         * @param a
         * @param b
         * @return
         */
        public static long gcd(long a, long b) {
            long r;
            if (a < b) {
                r = a;
                a = b;
                b = r;
            }
            while (b != 0) {
                r = a % b;
                a = b;
                b = r;
            }
            return a;
        }
    
        /**
         * 容斥原理 获得在n下所有与p互质的数的和
         * 
         * @param start
         * @param n
         * @param now
         * @return
         */
        private static long dfs(int start, int n, long now) {
            long res = 0, temp;
            for (int i = start; i < primeFactorLen; i++) {
                temp = lcm(now, primeFactor[i]);// 每一个开始,之后就是其最小公倍数
                res += getPrimeSum(temp, n) - dfs(i + 1, n, temp);
            }
            return res;
        }
    
        /**
         * 最小公倍数
         * 
         * @param now
         * @param i
         * @return
         */
        private static long lcm(long now, long i) {
            return (long) now / gcd(now, i) * i;
        }
    
        private static long getPrimeSum(long num, int n) {
            long temp = n / num;
            return temp * (temp + 1) / 2 * num;
        }
    
    }
    
    class Node {
        int x;
        int c;
    
        public Node(int x, int c) {
            this.x = x;
            this.c = c;
        }
    }
  • 相关阅读:
    redis的其他命令
    redis的有序集合ZSET(stored set)
    redis 的set数据类型
    redis 的hash数据类型
    php命令
    intellij idea
    生产者消费者问题
    JAVA sleep和wait 异同
    JAVA线程通信
    java线程同步--lock锁(JDK 5 新增)
  • 原文地址:https://www.cnblogs.com/xiaoxian1369/p/2698620.html
Copyright © 2011-2022 走看看