zoukankan      html  css  js  c++  java
  • HDU 4407 Sum ★(容斥原理)

    题目链接http://acm.hdu.edu.cn/showproblem.php?pid=4407 题目大意:给定初始n个数1..n,两个操作,①1 x y p  询问第x个数到第y个数中与p互质的数的和; ②:2 x y  把第x个数变成y 思路容斥原理求数区间[1..r]中与n互质的数的(个数&&和):HDU 4135 解决它的逆问题:求[1..r]中与n不互质的数的个数. 考虑n的素因子pi,则[1..r]中与pi不互质的数的个数是[r/pi]. 然而,如果我们单纯将所有结果相加,会得到错误答案。有些数可能被统计多次(被好几个素因子整除)。所以,我们要运用容斥原理来解决。 我们可以用2^k的算法求出所有的pi组合,然后计算每种组合的pi乘积,通过容斥原理来对结果进行加减处理。  
    int solve(int r,int n){
        int res = 0;
        vector  p;
        for (int i = 2; i * i <= n; i ++){
            if (n % i == 0){
                p.push_back(i);
                while(n % i == 0){
                    n = n / i;
                }
            }
        }
        if (n > 1){
            p.push_back(n);
        }
        for (int msk = 1; msk < (1 << p.size()); msk ++){
            int mult = 1, bit = 0;
            for (int i = 0; i < p.size(); i ++){
                if (msk & (1 << i)){
                    ++bit;
                    mult *= p[i];
                }
            }
            int cur = r / mult;
            if (bit % 2 == 1){
                res += cur;
            }
            else    res -= cur;
        }
        return r - res;
    }
    
      回到此题中,求个数和求和是一样的,我们只需要考虑怎么处理第二个操作——因为这道题m给的很小,所以我们完全可以每次询问都枚举以前改变的情况,至此问题解决。注意一点就是同一个地方的数可能被改两次,所以用map映射处理比较好。
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    #define MID(x,y) ((x+y)>>1)
    
    using namespace std;
    
    typedef long long LL;    //max long long == 9223372036854775807LL
    
    map  m;
    
    inline LL gcd(LL a, LL b){
        return b ? gcd(b, a % b) : a;
    }
    
    inline LL solve(int r,int n){
        if (r == 0) return 0;
        LL rans = 0;
        rans = (LL)r * LL(r + 1) / 2;
        LL res = 0;
        /*找n的素因子*/
        vector  p;
        for (int i = 2; i * i <= n; i ++){
            if (n % i == 0){
                p.push_back(i);
                while(n % i == 0){
                    n = n / i;
                }
            }
            if (n == 1) break;
        }
        if (n > 1){
            p.push_back(n);
        }
        /*找n的素因子*/
        for (int msk = 1; msk < (1 << p.size()); msk ++){
            int mult = 1;
            int bit = 0;
            for (int i = 0; i < p.size(); i ++){
                if (msk & (1 << i)){
                    ++bit;
                    mult *= p[i];
                }
            }
            LL cur = r / mult;
            LL curans = 0;
            curans = (cur + 1) * cur / 2 * mult;
            if (bit % 2 == 1){
                res += curans;
            }
            else    res -= curans;
        }
        return rans - res;
    }
    
    int main(){
        int t, n, M, pnum;
        scanf("%d",&t);
        while(t--){
            pnum = 0;
            m.clear();
            scanf("%d%d",&n,&M);
            for (int i = 0; i < M; i ++){
                int num;
                scanf("%d",&num);
                if (num == 2){
                    int a,b;
                    scanf("%d%d",&a, &b);
                    m[a] = b;
                }
                else{
                    int x,y,pp;
                    scanf("%d%d%d", &x, &y, &pp);
                    LL ans = solve(y, pp) - solve(x - 1, pp);
                    map  :: iterator it;
                    for (it = m.begin(); it != m.end(); it ++){
                        if (it->first >= x && it->first <= y){
                            if (gcd(it->first, pp) == 1){
                                ans -= it->first;
                            }
                            if (gcd(it->second, pp) == 1){
                                ans += it->second;
                            }
                        }
                    }
                    printf("%I64d\n",ans);
                }
            }
        }
        return 0;
    }
    
     
    举杯独醉,饮罢飞雪,茫然又一年岁。 ------AbandonZHANG
  • 相关阅读:
    eclipse新建工作空间后的常用设置
    Maven将代码及依赖打成一个Jar包的方式
    MemCache详细解读(转)
    memcached单机或热备的安装部署
    memcache的基本操作
    Java中int和String类型之间转换
    Linux中普通用户配置sudo权限(带密或免密)
    Java字符串中常用字符占用字节数
    java各种数据类型的数组元素的默认值
    validator
  • 原文地址:https://www.cnblogs.com/AbandonZHANG/p/4114182.html
Copyright © 2011-2022 走看看