zoukankan      html  css  js  c++  java
  • bzoj2301(莫比乌斯反演)

    经典题。首先得知道最基本的莫比乌斯求1-n和1-m之间有多少互质对

    然后根据下面论文

    http://wenku.baidu.com/view/fbe263d384254b35eefd34eb.html

    将每次查询的时间优化为n^(0.5)

    妙啊 妙啊

    还有要注意的一点,a,b,c,d不能在最开始的时候就除k

    不然的话对于k!=1时,会出错

    //
    //  main.cpp
    //  bzoj2301
    //
    //  Created by New_Life on 16/7/6.
    //  Copyright © 2016年 chenhuan001. All rights reserved.
    //
    
    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <math.h>
    #include <algorithm>
    using namespace std;
    #define N 100100
    
    //--莫比乌斯反演函数--//
    //说明:利用线性素数筛选顺便求了个mu
    //复杂度:O(n)
    int mu[N];
    
    void mobus()
    {
        bool mark[N];
        int prime[N];
        int pcnt=0;
        memset(mark,0,sizeof(mark));
        mu[1] = 1;
        for(int i=2;i<N;i++)
        {
            if(mark[i] == 0)
            {
                prime[pcnt++] = i;
                mu[i] = -1;
            }
            for(int j=0;j<pcnt && i*prime[j]<N;j++)
            {
                int tmp = i*prime[j];
                mark[tmp] = 1;
                if( i%prime[j] == 0 )
                {
                    mu[tmp] = 0;
                    break;
                }
                
                mu[tmp] = mu[i]*-1;
            }
        }
    }
    
    int sum[N];
    
    
    long long gaobili(int b,int d)
    {
        if(b<=0||d<=0) return 0;
        int m = min(b,d);
        long long ans = 0;
        while(m>=1)
        {
            int tb = b/( b/m +1 )+1;
            int td = d/( d/m +1 )+1;
            //前进的最大位置
            int tm = max(tb,td);
            ans += (long long)(sum[m]-sum[tm-1])*(b/m)*(d/m);
            m = tm-1;
        }
        return ans;
    }
    
    int main() {
        mobus();
        for(int i=1;i<N;i++)
            sum[i] += sum[i-1]+mu[i];
        int T;
        cin>>T;
        while(T--)
        {
            int a,b,c,d,k;
            scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
            //a/=k; b/=k; c/=k; d/=k;//这里很关键
            //搞bd
            long long ans = gaobili(b/k, d/k)-gaobili((a-1)/k, d/k)-gaobili(b/k, (c-1)/k)+gaobili((a-1)/k, (c-1)/k);
            printf("%lld
    ",ans);
        }
        return 0;
    }
    /*
    2
    2 5 1 5 1
    1 5 1 5 2
    
     */
  • 相关阅读:
    Fedora13下真正能用的源(2015-5-16亲测)
    Shellcoding教程:介绍ASM(译)
    Shellcoding教程:介绍ASM
    ubuntu解决pppoeconf和network-manager冲突时,可能问题的解决方法
    vue_router-link传参
    js_window.postMessage往不同窗口里面发送数据
    iframe_iframe引入其它页面
    css_去掉默认样式
    vue_常用组件install
    js_正则表达式
  • 原文地址:https://www.cnblogs.com/chenhuan001/p/5646504.html
Copyright © 2011-2022 走看看