• [SDOI2015]约数个数和


    题目描述

    设d(x)为x的约数个数,给定N、M,求 ij d(i*j)  (i<=n,j<=m)

    输入输出格式

    输入格式:

    输入文件包含多组测试数据。第一行,一个整数T,表示测试数据的组数。接下来的T行,每行两个整数N、M。

    输出格式:

    T行,每行一个整数,表示你所求的答案。

    输入输出样例

    输入样例#1:
    2
    7 4
    5 6
    输出样例#1:
    110
    121

    说明

    1<=N, M<=50000

    1<=T<=50000

    题解:

    已知推论:d(i*j)=∑ab[gcd(a,b)=1]  (a|i , b|j)

    原式化为

    ijab[gcd(a,b)=1]   (1<=i<=n&&1<=j<=m)

    =∑ijabdμ(d)       (d|a,d|b,d|i,d|j)

    =ijdμ(d)ab1     (d|i,d|j,1<=a<=n/i,1<=b<=m/j)   

    =ijdμ(d)*[n/i][m/j]

    =dμ(d)ij[n/id][m/jd]  (1<=d<=min(n,m),i<=n/d,j<=m/d)

    =dμ(d)*i[n/id]*j[m/jd]=dμ(d)*i[[n/d]/i]*j[[m/d]/j]

    令f(x)=∑[x/i] (1<=i<=x) 

    接下来用分块的方法在O(N√N)时间求出f(1~n)

    分块详见我写的http://www.cnblogs.com/Y-E-T-I/p/7255421.html

    每一次询问的时候也用分块的方法求ans=∑dμ(d)*[f(n/d)]*[f(m/d)]

    不过第三行似乎是多余的

    这个结论要记下来

    延伸结论

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 #include<cstring>
     5 using namespace std;
     6 bool vis[50001];
     7 int tot,prime[50001],mu[50001],n,m;
     8 long long ans,d[50001];
     9 void mobius()
    10 {int i,j;
    11 mu[1]=1;
    12     for (i=2;i<=50000;i++)
    13     {
    14         if (vis[i]==0)
    15         {
    16             tot++;
    17             prime[tot]=i;
    18             mu[i]=-1;
    19         }
    20         for (j=1;j<=tot,i*prime[j]<=50000;j++)
    21          {
    22              vis[i*prime[j]]=1;
    23              if (i%prime[j]==0)
    24              {
    25                  mu[i*prime[j]]=0;
    26                  break;
    27             }
    28                  mu[i*prime[j]]=-mu[i];
    29          }
    30     }
    31     for (i=1;i<=50000;i++)
    32     mu[i]+=mu[i-1];
    33 }
    34 void solve(int x)
    35 {int i;
    36     int pos=1;
    37     for (i=1;i<=x;i=pos+1)
    38     {
    39         pos=x/(x/i);
    40          d[x]+=(pos-i+1)*(x/i);
    41     }
    42 }
    43 void work()
    44 {int i;
    45     ans=0;
    46     int pos=1;
    47     for (i=1;i<=n;i=pos+1)
    48     {
    49         pos=min(n/(n/i),m/(m/i));
    50         ans+=(mu[pos]-mu[i-1])*(d[n/i])*(d[m/i]);
    51     }
    52 }
    53 int main()
    54 {int i,T;
    55     mobius();
    56      for (i=1;i<=50000;i++)
    57      solve(i);
    58       cin>>T;
    59       while (T--)
    60       {
    61         scanf("%d%d",&n,&m);
    62         if (n>m) swap(n,m);
    63          work();
    64          printf("%lld
    ",ans);
    65       }
    66 }
  • 相关阅读:
    【洛谷】P2880 [USACO07JAN]平衡的阵容Balanced Lineup(st表)
    【洛谷】P1052 过河(状压dp)
    【洛谷】P1541 乌龟棋(四维背包dp)
    【BZOJ】4721: [Noip2016]蚯蚓 / 【洛谷】P2827 蚯蚓(单调队列)
    【洛谷】P1064 金明的预算方案(dp)
    【洛谷】P3908 异或之和(异或)
    【洛谷】P2434 [SDOI2005]区间(暴力)
    【洛谷】P2694 接金币(排序)
    【BZOJ】1012: [JSOI2008]最大数maxnumber /【洛谷】1198(线段树)
    【游记】noip2017酱油记
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/7280004.html
Copyright © 2020-2023  润新知