• [SDOI2015]约数个数和 莫比乌斯反演


    ~~~题面~~~

    题解:

    为什么SDOI这么喜欢莫比乌斯反演,,,

    首先有一个结论$$d(ij) = sum_{x|i}sum_{y|j}[gcd(x, y) == 1]$$
    为什么呢?
    首先,可以看做从两个数中分别取一些不重叠的质数的$k_{i}$次方,组成新数的方案数。
    那如果有需要重叠的部分怎么办?
    可以看做全都在第一个or第二个数中取。
    但是一个数的次数不够怎么办呢?
    相当于以1为媒介,可以简介统计到这些情况
    比如$2^{3} cdot 2^{2}  = 2^{5}$可以看成$1, 2^{3}$ + $1, 2^{2}$,这样就可以做到分别枚举了指数从1到5的情况了;
    $$ans = sum_{i = 1}^{n}sum_{j = 1}^{m}sum_{x | i}sum_{y | j}[gcd(x, y) == 1]$$
    $$ans = sum_{x = 1}^{n}sum_{y = 1}^{m} lfloor{frac{n}{x}} floor lfloor{frac{m}{y}} floor [gcd(x, y) == 1]$$<---改成枚举x和y,然后统计有多少对i,j中分别含有因数x,y
    设$$f(d) = sum_{x = 1}^{n}sum_{y = 1}^{m} lfloor{frac{n}{x}} floor lfloor{frac{m}{y}} floor [gcd(x, y) == d]$$, $$g(x) = sum_{x | d}^{min(n, m)}{f(d)}$$
    那么$ans = f(1)$
    反演一下得到:$$f(n)  = sum_{n | d}mu(frac{d}{n}) cdot g(d)$$
    接下来就是怎么求$g(d)$了。
    $$g(d) = sum_{x = 1}^{n}sum_{y = 1}^{m} lfloor{frac{n}{x}} floor lfloor{frac{m}{y}} floor [d | gcd(x, y)]$$
    $d | gcd(x, y)$ ---> $d | x + d | y$ ,因为$x | n + y | m$ ---> $d | n + d | m$
    所以枚举$d_{i}$就符合条件了,$lfloor{frac{n}{dx}} floor$ ---> $dx$倍数的个数,即有多少i,j的搭配是可以满足$[d|gcd(x, y)]$的
    $$g(d) = sum_{x = 1}^{ lfloor{frac{n}{d}} floor }sum_{y = 1}^{ lfloor{frac{m}{d}} floor } lfloor{frac{n}{dx}} floor lfloor{frac{m}{dy}} floor$$
    于是现在就是要求$f(1)$
    $$f(1) = sum_{d = 1}^{min(n, m)}{mu(frac{d}{1})g(d)}$$
    $$= sum_{d = 1}^{min(n, m)}{mu(d)g(d)}$$
    $$= sum_{d = 1}^{min(n, m)}{mu(d) cdot sum_{x = 1}^{ lfloor{frac{n}{d}} floor }sum_{y = 1}^{ lfloor{frac{m}{d}} floor } lfloor{frac{n}{dx}} floor lfloor{frac{m}{dy}} floor}$$
    这个式子可以整数分块。
    设$N = frac{n}{d}$, $M = frac{m}{d}$,那么
    $$= sum_{d = 1}^{min(n, m)}{mu(d) cdot sum_{x = 1}^{ N }sum_{y = 1}^{ M } lfloor{frac{N}{x}} floor lfloor{frac{M}{y}} floor}$$
    $$= sum_{d = 1}^{min(n, m)}{mu(d) cdot sum_{x = 1}^{ N}{lfloor{frac{N}{x}} floor} sum_{y = 1}^{M}  {lfloor{frac{M}{y}} floor}}$$
    而$N = lfloor{frac{n}{d}} floor$, $M = lfloor{frac{m}{d}} floor$有很多相同的区间段,所以可以整数分块求。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define R register int
     4 #define AC 50100
     5 #define ac 50000
     6 #define LL long long
     7 int n, m, tot, t;
     8 LL ans;
     9 int prime[AC];
    10 LL mu[AC], s[AC];
    11 bool z[AC];
    12 
    13 inline int read()
    14 {
    15     int x = 0;char c = getchar();
    16     while(c > '9' || c < '0') c = getchar();//error!!!又一次打错了读入优化。。。是||啊
    17     while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    18     return x;
    19 }
    20 
    21 void pre()
    22 {
    23     int x;
    24     mu[1] = 1;
    25     for(R i = 2; i <= ac; i++)
    26     {
    27         if(!z[i]) prime[++tot] = i, mu[i] = -1;
    28         for(R j = 1; j <= tot; j++)
    29         {
    30             x = prime[j];
    31             if(x * i > ac) break;
    32             z[x * i] = true;
    33             if(!(i % x)) break;
    34             mu[i * x] = -mu[i]; 
    35         }
    36     }
    37     for(R i = 1; i <= ac; i++) mu[i] += mu[i-1];    
    38     int pos;
    39     for(R i = 1; i <= ac; i++) 
    40     {
    41         for(R j = 1; j <= i; j = pos + 1)
    42         {
    43             pos = i / (i / j);
    44             s[i] += (LL)(i / j) * (LL)(pos - j + 1);
    45         }
    46     }
    47 //    for(R i = 1; i <= 30; i++) printf("%lld
    ", s[i]);
    48 }
    49 
    50 void work()
    51 {
    52     t = read();
    53     while(t--)
    54     {
    55         n = read(), m = read(), ans = 0;
    56         //scanf("%d%d", &n, &m);ans = 0;
    57         int pos, b = min(n, m);
    58         for(R i = 1; i <= b; i = pos + 1)
    59         {
    60             pos = min(n / (n / i), m / (m / i));
    61             ans += (mu[pos] - mu[i - 1]) * s[n / i] * s[m / i];
    62         }
    63         printf("%lld
    ", ans);
    64     }
    65 }
    66 
    67 int main()
    68 {
    69 //    freopen("in.in", "r", stdin);
    70     pre();
    71     work();
    72 //    fclose(stdin);
    73     return 0;
    74 }
  • 相关阅读:
    【杂谈】对RMI(Remote Method Invoke)的认识
    【杂谈】对CopyOnWriteArrayList的认识
    【杂谈】Java I/O的底层实现
    揭开Future的神秘面纱——结果获取
    揭开Future的神秘面纱——任务执行
    【详解】ThreadPoolExecutor源码阅读(三)
    【详解】ThreadPoolExecutor源码阅读(二)
    【详解】ThreadPoolExecutor源码阅读(一)
    小程序页面数据回传
    记录一个吃过前端内存的坑
  • 原文地址:https://www.cnblogs.com/ww3113306/p/9488765.html
Copyright © 2020-2023  润新知