• BZOJ2301 莫比乌斯反演


    题意:a<=x<=b,c<=y<=d,求满足gcd(x,y)=k的数对(x,y)的数量         ((x,y)和(y,x)不算同一个)

    比hdu1695多加了个下界,还有顺序不一样的也算上了。

    因为G(x,y)本来就是顺序不一样的算不同方案,所以这题的公式就是:

    Ans=G(b/k,d/k)-G((a-1)/k,d/k)-G(b/k,(c-1)/k)+G((a-1)/k,(c-1)/k)

    但是本题数据很大,直接计算会TLE,

    有一个优化:http://www.cnblogs.com/zhsl/p/3269288.html

    //calc G(a,b)
    
    LL _G(int a,int b)          //朴素算法
    {
        int tx=min(a,b),ty=max(a,b);
        LL ans = 0;
        for(int i = 1; i <= tx; i++)
            ans += (LL)mu[i]*(tx/i)*(ty/i);
        return ans;
    }
    
    LL G(int n,int m)           //加分块优化
    {
        LL ans = 0;
        if(n > m)   swap(n,m);
        for(int i = 1, la = 0; i <= n; i = la+1)
        {
            la = min(n/(n/i),m/(m/i));
            ans += (LL)(msum[la] - msum[i-1])*(n/i)*(m/i);      //事先预处理:msum[n]=SUM(mu[1..n])
        }
        return ans;
    }

    不知为什么自己测AC了结果bzoj上一直RuntimeError......要完蛋了orz,改成scanf和printf就过了

     1 #include <iostream>
     2 #include <cstring>
     3 #include <cmath>
     4 #include <cstdio>
     5 using namespace std;
     6 #define LL long long
     7 #define MMX 50100
     8 LL mu[MMX],msum[MMX];
     9 bool check[MMX];
    10 int prime[MMX];
    11 int a,b,c,d,k,T;
    12 
    13 void Moblus()
    14 {
    15     memset(check,false,sizeof(check));
    16     mu[1] = 1;
    17     int tot = 0;
    18     for(int i = 2; i <= MMX; i++)
    19     {
    20         if( !check[i] )
    21         {
    22             prime[tot++] = i;
    23             mu[i] = -1;
    24         }
    25         for(int j = 0; j < tot; j++)
    26         {
    27             if(i * prime[j] > MMX) break;
    28             check[i * prime[j]] = true;
    29             if( i % prime[j] == 0)
    30             {
    31                 mu[i * prime[j]] = 0;
    32                 break;
    33             }
    34             else
    35             {
    36                 mu[i * prime[j]] = -mu[i];
    37             }
    38         }
    39     }
    40     msum[1]=mu[1];
    41     for (int i=2;i<=MMX;i++)
    42         msum[i]=msum[i-1]+mu[i];
    43 }
    44 
    45 //calc G(a,b)
    46 LL _G(int a,int b)          //朴素算法
    47 {
    48     int tx=min(a,b),ty=max(a,b);
    49     LL ans = 0;
    50     for(int i = 1; i <= tx; i++)
    51         ans += (LL)mu[i]*(tx/i)*(ty/i);
    52     return ans;
    53 }
    54 
    55 LL G(int n,int m)           //加分块优化
    56 {
    57     LL ans = 0;
    58     if(n > m)   swap(n,m);
    59     for(int i = 1, la = 0; i <= n; i = la+1)
    60     {
    61         la = min(n/(n/i),m/(m/i));
    62         ans += (LL)(msum[la] - msum[i-1])*(n/i)*(m/i);      //事先预处理:msum[n]=SUM(mu[1..n])
    63     }
    64     return ans;
    65 }
    66 
    67 int main()
    68 {
    69     //freopen("in.txt","r",stdin);
    70     //freopen("out.txt","w",stdout);
    71 
    72     cin>>T;
    73     Moblus();
    74     while (T--)
    75     {
    76         scanf("%d%d%d%d%d",&a,&b,&c,&d,&k);
    77         //cout<<G(b/k,d/k)<<"  "<<G((a-1)/k,d/k)<<"  "<<G(b/k,(c-1)/k)<<"  "<<G((a-1)/k,(c-1)/k)<<endl;
    78         LL res=G(b/k,d/k)-G((a-1)/k,d/k)-G(b/k,(c-1)/k)+G((a-1)/k,(c-1)/k);
    79         printf("%lld
    ",res);
    80     }
    81     return 0;
    82 }
    View Code

    实测:

    朴素算法:   

    1005 root 1002 Accepted 380K 47400MS G++ 1.6K 2014-11-15 15:37:03

    优化算法:

    1014 root 1002 Accepted 952K 6011MS G++ 1.81K 2014-11-15 17:17:59
  • 相关阅读:
    动态模板列更新数据分页的例子
    Oracle SCN机制解析
    阻止特定的ip登陆数据库的2种方法 (轉)
    Oracle动态执行SQL四种方式的例子
    使用Oracle的DBMS_SQL包执行动态SQL语句
    Oracle XML DB之浅入浅出
    将oracle设为归档模式和非归档模式启动的方法
    如何修改Oracle數據庫字符集
    (原創)C#使用QueryTables導出到Excel
    常用SQL語句2
  • 原文地址:https://www.cnblogs.com/pdev/p/4099449.html
Copyright © 2020-2023  润新知