BZOJ 4816 [Sdoi2017]数字表格

来源:互联网 发布:怎样看淘宝退款率 编辑:程序博客网 时间:2024/06/04 19:24

莫比乌斯反演

不妨设 n<m
ni=1mj=1f[(i,j)]
考虑一个f的贡献,也就是变成
nd=1f[d]ni=1mj=1[(i,j)=1]
然后上面那个就是区间内gcd为定值的计数,大力反演
nd=1f[d]d|inimiμ[id]
也就是
nd=1f[d]ndi=1nidmidμ[i]
用指数的整除只有根号段的性质来搞一下,指数相加等于底数相乘,即用T来枚举id,变成
nT=1(d|Tf[d]μ[Td])nTmT
括号里的东西只跟T有关,预处理,然后因为指数的答案在整除下分段,根号枚举每一段即可O(Tnlogn)。这里的T是数据组数了……

#include<cstdio>#include<algorithm>#define N 1000005#define MOD 1000000007using namespace std;namespace runzhe2000{    typedef long long ll;    int f[N], f_inv[N], g[N], preg[N], preg_inv[N], mu[N], prime[N], notprime[N], pcnt;    int fpow(int a, int b)    {        int r = 1;        for(; b; b >>= 1)        {            if(b & 1) r = (ll) r * a % MOD;            a = (ll) a * a % MOD;        }        return r;    }    void main()    {        f[1] = f_inv[1] = 1; for(int i = 2; i < N; i++) f[i] = (ll)(f[i-1] + f[i-2]) % MOD, f_inv[i] = fpow(f[i], MOD-2);        mu[1] = 1; for(int i = 2; i < N; i++)        {            if(!notprime[i]) prime[++pcnt] = i, mu[i] = -1;            for(int j = 1; j <= pcnt && prime[j] * i < N; j++)            {                notprime[prime[j] * i] = 1;                if(i % prime[j] == 0) break;                else mu[prime[j] * i] = - mu[i];            }        }        for(int i = 1; i < N; i++) g[i] = 1;        for(int i = 1; i < N; i++)            for(int j = i; j < N; j += i)            {                if(mu[j/i] ==  1) g[j] = (ll) g[j] * f[i] % MOD;                if(mu[j/i] == -1) g[j] = (ll) g[j] * f_inv[i] % MOD;            }        preg[0] = preg_inv[0] = 1; for(int i = 1; i < N; i++) preg[i] = (ll) preg[i-1] * g[i] % MOD, preg_inv[i] = fpow(preg[i], MOD-2);        int T, n, m; scanf("%d",&T);        for(; T--; )        {            scanf("%d%d",&n,&m); int ans = 1;            if(n > m) swap(n, m);            for(int i = 1, j; i <= n; i = j + 1)            {                j = min(n/(n/i), m/(m/i)); j > n ? j = n : 0;                ans = (ll) ans * fpow((ll)preg[j] * preg_inv[i-1] % MOD, (ll)(n/i)*(m/i)%(MOD-1)) % MOD;            }            printf("%d\n",ans);        }    }}int main(){    runzhe2000::main();}
0 0
原创粉丝点击