4816: [Sdoi2017]数字表格

Time Limit: 50 Sec  Memory Limit: 128 MB

Description

Doris刚刚学习了fibonacci数列。用f[i]表示数列的第i项,那么
f[0]=0
f[1]=1
f[n]=f[n-1]+f[n-2],n>=2
Doris用老师的超级计算机生成了一个n×m的表格,第i行第j列的格子中的数是f[gcd(i,j)],其中gcd(i,j)表示i,j的最大公约数。Doris的表格中共有n×m个数,她想知道这些数的乘积是多少。答案对10^9+7取模。

Input

有多组测试数据。

第一个一个数T,表示数据组数。
接下来T行,每行两个数n,m
T<=1000,1<=n,m<=10^6

Output

输出T行,第i行的数是第i组数据的结果

Sample Input

3
2 3
4 5
6 7

Sample Output

1
6
960

题解

这道题很好地延续了SDOI的优良传统,考了一道莫比乌斯反演以供娱乐。

由于我们一眼发现了这是一道莫比乌斯反演水题,正如做所有的莫比乌斯反演一样,我们把要求的式子先写出来并推导

\begin{eqnarray*}
ans & = & \prod_{i}^{n}\prod _{j}^{m}f( \gcd(i,j) ) \\
& = & \prod_{k}^{n}f(k) ^ {\sum_{i}^{\frac{n}{k}}\sum_{j}^{\frac{m}{k}}[\gcd(i,j)=1]} \\
& = & \prod_{k}^{n}f(k) ^ {\sum_{i}^{\frac{n}{k}}\sum_{j}^{\frac{m}{k}}\sum_{x\mid{i}\&x\mid{j}}~~\mu(x)} \\
& = & \prod_{k}^{n}\prod_{x}^{\frac{n}{k}}(f(k) ^ {\mu(x)})^{\frac{n}{kx}\frac{m}{kx}}
\end{eqnarray*}

为了能够把\(f(k) ^ {\mu(x)}\)提出来,显然,我们可以设\(T=kx\),\(g(T)=\prod_{k\mid{T}}f(k) ^ {\mu(\frac{T}{k})}\)

化简得到\(ans = \prod_{T}^{n}g(T)^{\frac{n}{T}\frac{m}{T}}\)

求出$f$以及$f$的逆元,线性筛求$\mu$,Dirichlet卷积求出$g$,然后计算$g$的前缀积$g'$以及$g'$的逆元

查询使用大众喜闻乐见的分块,至此,我们切掉了这道水题。

代码

#include<bits/stdc++.h>
using namespace std;
template <class _T> inline void read(_T &_x) {
int _t; bool flag = false;
while ((_t = getchar()) != '-' && (_t < '' || _t > '')) ;
if (_t == '-') _t = getchar(), flag = true; _x = _t - '';
while ((_t = getchar()) >= '' && _t <= '') _x = _x * + _t - '';
if (flag) _x = -_x;
}
typedef long long LL;
const int maxn = ;
const int mod = ;
int f[maxn], f_re[maxn], mu[maxn], g[maxn], g_re[maxn];
bool vis[maxn]; int prime[maxn / ], pcnt;
#define trans(x) ((int)((LL)x % mod))
#define reg register
inline void update(int &a, reg int b) {
a = trans(a * b);
if (a < ) a += mod;
}
inline int qpower(int a, reg LL b) {
int ret = ;
while (b) {
if (b & ) update(ret, a);
update(a, a), b >>= ;
}
return ret;
}
inline int calc(reg int a, reg int b) {
if (b == ) return ;
return b < ? f_re[a] : f[a];
}
void init() {
f[] = , f[] = f_re[] = g[] = mu[] = ;
reg int i, j;
for (i = ; i < maxn; ++i) {
f[i] = f[i - ] + f[i - ];
if (f[i] >= mod) f[i] -= mod;
f_re[i] = qpower(f[i], mod - );
}
for (i = ; i < maxn; ++i) {
g[i] = ;
if (!vis[i]) {
prime[++pcnt] = i;
mu[i] = -;
}
for (j = ; j <= pcnt && prime[j] * i < maxn; ++j) {
vis[i * prime[j]] = true;
if (i % prime[j] == ) {
mu[i * prime[j]] = ;
break;
}
mu[i * prime[j]] = -mu[i];
}
}
for (i = ; i * i < maxn; ++i) {
update(g[i * i], calc(i, mu[i]));
for (j = i + ; i * j < maxn; ++j)
update(g[i * j], trans(calc(i, mu[j]) * calc(j, mu[i])));
}
g[] = g_re[] = ;
for (i = ; i < maxn; ++i) {
update(g[i], g[i - ]);
g_re[i] = qpower(g[i], mod - );
}
}
inline int query(reg int a, reg int b) {
if (a > b) {int t = a; a = b, b = t; }
int ret = ;
for (reg int i = , j, x, y; i <= a; i = j + ) {
x = a / i, y = b / i;
j = min(a / x, b / y);
update(ret, qpower(trans(g[j] * g_re[i - ]), (LL)x * y));
}
return ret;
}
int main() {
//freopen(".in", "r", stdin);
//freopen(".out", "w", stdout);
init();
int T, a, b; read(T);
while (T--) {
read(a), read(b);
printf("%d\n", query(a, b));
}
return ;
}

BZOJ4816 数字表格的更多相关文章

  1. 【BZOJ4816】数字表格(莫比乌斯反演)

    [BZOJ4816]数字表格(莫比乌斯反演) 题面 BZOJ 求 \[\prod_{i=1}^n\prod_{j=1}^mf[gcd(i,j)]\] 题解 忽然不知道这个要怎么表示... 就写成这样吧 ...

  2. 【BZOJ4816】【SDOI2017】数字表格 [莫比乌斯反演]

    数字表格 Time Limit: 50 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description Doris刚刚学习了fibonac ...

  3. BZOJ 2154: Crash的数字表格 [莫比乌斯反演]

    2154: Crash的数字表格 Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 2924  Solved: 1091[Submit][Status][ ...

  4. 【BZOJ】【2154】Crash的数字表格

    莫比乌斯反演 PoPoQQQ讲义第4题 题解:http://www.cnblogs.com/jianglangcaijin/archive/2013/11/27/3446169.html 感觉两次sq ...

  5. 【莫比乌斯反演】关于Mobius反演与lcm的一些关系与问题简化(BZOJ 2154 crash的数字表格&&BZOJ 2693 jzptab)

    BZOJ 2154 crash的数字表格 Description 今天的数学课上,Crash小朋友学习了最小公倍数(Least Common Multiple).对于两个正整数a和b,LCM(a, b ...

  6. 【BZOJ 2154】Crash的数字表格 (莫比乌斯+分块)

    2154: Crash的数字表格 Description 今天的数学课上,Crash小朋友学习了最小公倍数(Least Common Multiple).对于两个正整数a和b,LCM(a, b)表示能 ...

  7. BZOJ 4816 数字表格

    首先是惯例的吐槽.SDOI题目名称是一个循环,题目内容也是一个循环,基本上过几年就把之前的题目换成另一个名字出出来,喜大普奔亦可赛艇.学长说考SDOI可以考出联赛分数,%%%. 下面放解题报告.并不喜 ...

  8. BZOJ:4816: [Sdoi2017]数字表格

    4816: [Sdoi2017]数字表格 Time Limit: 50 Sec  Memory Limit: 128 MBSubmit: 501  Solved: 222[Submit][Status ...

  9. [Sdoi2017]数字表格 [莫比乌斯反演]

    [Sdoi2017]数字表格 题意:求 \[ \prod_{i=1}^n \prod_{j=1}^m f[(i,j)] \] 考场60分 其实多推一步就推倒了... 因为是乘,我们可以放到幂上 \[ ...

随机推荐

  1. 开放地址法散列表ADT

    数据结构定义如下: typedef unsigned int Index; typedef Index Position; struct HashTbl; typedef struct HashTbl ...

  2. Hadoop初探

    本文转自:https://blog.csdn.net/column/details/14334.html 前言 Hadoop是什么? 用百科上的话说:“Hadoop是一个由Apache基金会所开发的分 ...

  3. 一道面试题:StringBuffer a=new StringBuffer ("A"); StringBuffer b=new StringBuffer

    前几天又看到这个面试题,再次看看 public class Jtest{ public static void main(String[] args) { StringBuffer a=new Str ...

  4. SQL查找删除重复行

    本文讲述如何查找数据库里重复的行.这是初学者十分普遍遇到的问题.方法也很简单.这个问题还可以有其他演变,例如,如何查找“两字段重复的行”(#mysql IRC 频道问到的问题) 如何查找重复行 第一步 ...

  5. Redis:主从复制

    前言 在前面的两篇文章中,分别介绍了Redis的内存模型和Redis的持久化. 在Redis的持久化中曾提到,Redis高可用的方案包括持久化.主从复制(及读写分离).哨兵和集群.其中持久化侧重解决的 ...

  6. BZOJ3107 CQOI2013二进制A+B(动态规划)

    显然答案只与a.b.c中各自1的个数及位数有关.a.b只考虑前i位怎么填时,c最多在第i+1位上为1,而第i+1位及之后的a.b怎么填都不会对前i位造成影响.于是设f[n][i][j][k][0/1] ...

  7. Nastya Studies Informatics CodeForces - 992B(增长姿势)

    有增长姿势了 如果a * b == lcm * gcd 那么a和b为lcm因数  这个我之前真不知道emm... #include <bits/stdc++.h> #define mem( ...

  8. 何登成大神对Innodb加锁的分析

    背景 MySQL/InnoDB的加锁分析,一直是一个比较困难的话题.我在工作过程中,经常会有同事咨询这方面的问题.同时,微博上也经常会收到MySQL锁相关的私信,让我帮助解决一些死锁的问题.本文,准备 ...

  9. swift网络数据请求方法

    搭建一个apache服务器,用php编写一个返回给客户端请求数据的脚本 <?php // header("Content-type:text/html;charset=utf-8&qu ...

  10. mimikazhi Kerberos Modules

    Kerberos Modules 1.   .#####.   mimikatz 2.0 alpha (x64) release "Kiwi en C" (Oct  9201500 ...