Portal -->broken qwq

Description

​   求\(\prod\limits_{i=1}^n\prod\limits_{j=1}^m f[gcd(i,j)](mod\ 10^9+7)\),其中\(f[0]=0,f[1]=1,f[i]=f[i-1]+f[i-2]\)

​   数据范围:多组数据,数据组数\(T<=1000,1<=n,m<=10^6\)

Solution

​​   这题。。一开始我觉得这题好像直接求个范围内\(gcd(i,j)=d\)的对数就做完了qwq

​​   式子长这个样子

\[\begin{aligned}
Ans&=\prod\limits_{d=1}^{min(n,m)}f(d)^{s(d)}\\
s(d)&=\sum\limits_{i=1}^n\sum\limits_{j=1}^m[gcd(i,j)=d]\\
&=\sum\limits_{k=1}^{\lfloor\frac{min(n,m)}{d}\rfloor}\mu(k)\lfloor\frac{n}{kd}\rfloor\lfloor\frac{m}{kd}\rfloor
\end{aligned}
\]

​   然后发现单组\(O(n\sqrt n logn)\)然后数据组数\(1000\)==(不过还是有60)

​  (然而实际上也是可以做的==详见后面的update)

​​  

​​   正解并没有题面那么简单qwq实际上正解很妙qwq

​​   我们考虑构造一个函数\(g(x)\),满足:

\[f[n]=\prod\limits_{d|n}g(d)
\]

​​   这样一来我们就可以把原来的式子化一下变成:

\[\begin{aligned}
&\prod\limits_{i=1}^n\prod\limits_{j=1}^mf[gcd(i,j)]\\
=&\prod\limits_{i=1}^n\prod\limits_{j=1}^m\prod_{d|i,d|j}g(d)\\
=&\prod\limits_{d=1}^{min(n,m)}g(d)^{\lfloor\frac{n}{d}\rfloor\lfloor\frac{m}{d}\rfloor}
\end{aligned}
\]

​​   然后这样我们就不用再在外面枚举一次了,单组复杂度\(O(\sqrt nlogn)\)

​​   前提是我们知道\(g(d)\)的前缀积

​   这个东西长得跟反演式子差不多,考虑反演式子的容斥解释,本质上就是容斥的加加减减,换成乘法的话就是乘除就好了,所以我们直接将\(\mu\)搬到指数上面就好了

\[g(n)=\prod\limits_{d|n}f(d)^{\mu(\frac{n}{d})}
\]

​   这个可以大力枚举约数什么的直接预处理

​   然后这题就做完啦ovo

​  

​   重大update!!

​   这题其实用最上面一开始推的那个式子也是可以做的!只不过。。我们可以把指数的式子少化一步变成:

\[s(d)=\sum\limits_{i=1}^{\lfloor\frac{n}{d}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{m}{d}\rfloor}[gcd(i,j)=1]
\]

​   然后我们会发现底数也是可以分块的!我们预处理一下\(f\)的前缀积,然后直接大力分块一下就好了(注意\(f[0]=0\)的情况在求逆元的时候返回\(1\))

​   这种做法的话。。很暴力但是可以压线过==算是一种水法吧。。不过因为式子非常好推场上比较容易想到所以还是记录一下

​   复杂度的话给给全说因为和不预处理的杜教筛形式类似所以是。。\(O(n^{\frac{3}{4}})\)的然后一定要算的话。。再加上一个\(\sqrt n logn\)(快速幂)

​  

​​   正解的代码大概长这个样子

#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std;
const int N=1e6+10,MOD=1e9+7;
int f[N],g[N],p[N],miu[N],invf[N],invg[N];
int vis[N];
int n,m,T,ans;
int add(int x,int y){return (1LL*x+MOD+y)%MOD;}
int mul(int x,int y){return 1LL*x*y%MOD;}
int ksm(int x,ll y){
int ret=1,base=x;
for (;y;y>>=1,base=mul(base,base))
if (y&1) ret=mul(ret,base);
return ret;
}
int inv(int x){return ksm(x,MOD-2);}
void prework(int n){
int cnt=0;
miu[1]=1;
for (int i=2;i<=n;++i){
if (!vis[i])
p[++cnt]=i,miu[i]=-1;
for (int j=1;j<=cnt&&p[j]*i<=n;++j){
vis[i*p[j]]=true;
if (i%p[j]==0){
miu[i*p[j]]=0;
break;
}
else
miu[i*p[j]]=-miu[i];
}
}
f[0]=0; f[1]=1; g[1]=1;
for (int i=2;i<=n;++i) f[i]=add(f[i-1],f[i-2]),g[i]=1;
for (int i=1;i<=n;++i) invf[i]=inv(f[i]);
for (int i=1;i<=n;++i)
for (int j=i;j<=n;j+=i){
if (miu[j/i]==-1)
g[j]=mul(g[j],invf[i]);
else if (miu[j/i]==1)
g[j]=mul(g[j],f[i]);
}
for (int i=2;i<=n;++i) g[i]=mul(g[i],g[i-1]);
invg[0]=1;
for (int i=1;i<=n;++i) invg[i]=inv(g[i]);
}
int solve(){
int ret=1;
if (n>m) swap(n,m);
for (int i=1,pos=0;i<=n;i=pos+1){
pos=min(n/(n/i),m/(m/i));
ret=mul(ret,ksm(mul(g[pos],invg[i-1]),1LL*(n/i)*(m/i)));
}
return ret;
} int main(){
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
#endif
scanf("%d",&T);
prework(N-10);
for (int o=1;o<=T;++o){
scanf("%d%d",&n,&m);
ans=solve();
printf("%d\n",ans);
}
}

​  

​   水法的代码大概长这个样子

#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std;
const int N=1e6+10,MOD=1e9+7,inf=2147483647;
ll f[N],miu[N],p[N];
int vis[N];
int n,m,T;
int mul(int x,int y){return 1LL*x*y%MOD;}
int add(int x,int y){return (1LL*x+y)%MOD;}
void prework(int n){
int cnt=0;
miu[1]=1;
for (int i=2;i<=n;++i){
if (!vis[i]){
p[++cnt]=i; miu[i]=-1;
}
for (int j=1;j<=cnt&&i*p[j]<=n;++j){
vis[i*p[j]]=1;
if (i%p[j])
miu[i*p[j]]=-miu[i];
else{
miu[i*p[j]]=0; break;
}
}
}
for (int i=2;i<=n;++i) miu[i]+=miu[i-1];
f[0]=0; f[1]=1;
for (int i=2;i<=n;++i) f[i]=add(f[i-1],f[i-2]);
for (int i=2;i<=n;++i) f[i]=mul(f[i],f[i-1]);
}
int ksm(int x,ll y){
int ret=1,base=x;
for (;y;y>>=1,base=mul(base,base))
if (y&1) ret=mul(ret,base);
return ret;
}
int inv(int x){return x==0?1:ksm(x,MOD-2);}
ll s(int n,int m){
ll ret=0;
for (int i=1,pos=0;i<=n;i=pos+1){
pos=min(n/(n/i),m/(m/i));
//ret=add(ret,mul(add(miu[pos],-miu[i-1]),mul(n/i,m/i)));
ret+=1LL*(n/i)*(m/i)*(miu[pos]-miu[i-1]);
}
return ret;
}
int solve(int n,int m){
int ret=1;
for (int i=1,pos=0;i<=n;i=pos+1){
pos=min(n/(n/i),m/(m/i));
ret=mul(ret,ksm(mul(f[pos],inv(f[i-1])),s(n/i,m/i)));
}
return ret;
} int main(){
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
#endif
scanf("%d",&T);
prework(N-10);
for (int i=1;i<=T;++i){
scanf("%d%d",&n,&m);
if (n>m) swap(n,m);
printf("%d\n",solve(n,m));
}
}

数字表格(product)的更多相关文章

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

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

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

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

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

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

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

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

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

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

  6. BZOJ 4816 数字表格

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

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

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

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

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

  9. 【BZOJ2154】Crash的数字表格(莫比乌斯反演)

    [BZOJ2154]Crash的数字表格(莫比乌斯反演) 题面 BZOJ 简化题意: 给定\(n,m\) 求\[\sum_{i=1}^n\sum_{j=1}^mlcm(i,j)\] 题解 以下的一切都 ...

随机推荐

  1. String、StringBuffer、StringBuilder有什么区别

    区别 先说说String和StringBuffer/StringBuilder: String是标准的不可变类,是一个字符串常量池,并且声明的对象在方法中是唯一存在的. StringBuffer/St ...

  2. leetcode26_C++删除排序数组中的重复项

    给定一个排序数组,你需要在原地删除重复出现的元素,使得每个元素只出现一次,返回移除后数组的新长度. 不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成. 示例 1 ...

  3. 小数第n位:高精度

    小数第n位 问题描述 我们知道,整数做除法时,有时得到有限小数,有时得到无限循环小数. 如果我们把有限小数的末尾加上无限多个0,它们就有了统一的形式. 本题的任务是:在上面的约定下,求整数除法小数点后 ...

  4. Node2vec 代码分析

    Node2vec 代码从Github上clone到本地,主要是main.py和node2vec.py两个文件. 下面把我的读代码注释放到上面来, import numpy as np import n ...

  5. Python爬虫入门(1-2):综述、爬虫基础了解

    大家好哈,最近博主在学习Python,学习期间也遇到一些问题,获得了一些经验,在此将自己的学习系统地整理下来,如果大家有兴趣学习爬虫的话,可以将这些文章作为参考,也欢迎大家一共分享学习经验. Pyth ...

  6. 1019psp

    1.本周psp: 2.本周进度条: 3.累计进度图(折线图): 4.psp饼状图:

  7. 【Alpha】阶段第一次Scrum Meeting

    [Alpha]阶段第一次Scrum Meeting 工作情况 团队成员 今日已完成任务 明日待完成任务 刘峻辰 后端接口开发 测试接口,修正bug 赵智源 撰写测试方案书 部署实际任务和编写测试样例 ...

  8. 周总结<5>

    周次 学习时间 新编写代码行数 博客量(篇) 学到知识点 12 10 100 1 路由器的设置(ospf协议):网页设计:哈夫曼树(C语言数构) Html案例: <!DOCTYPE html P ...

  9. Hibernate:工作原理

    Hibernate的工作原理图如下所示:

  10. Swift-存储属性,计算属性,类属性

    //类的属性定义 class Student: NSObject { // 定义属性 // 定义存储属性 var age : Int = var name :String? var mathScore ...