首页 > 其他分享 >「SDOI2017」数字表格 题解

「SDOI2017」数字表格 题解

时间:2023-05-13 09:45:35浏览次数:59  
标签:表格 题解 ll 莫比 mu 反演 SDOI2017 prod sum

4114 「SDOI2017」数字表格 题解

个人评价:好题且套路多

算法标签

莫比乌斯反演

题目难度:2700

题面

看我

分析题面

多组数据,每次给出\(n,m\),求解\(\prod_{i=1}^n\prod_{j=1}^mF_{gcd(i,j)}\),其中\(F\)是斐波那契数列

问题分析

第一眼化出这个式子肯定是一脸懵,毕竟我们现在做的大多数莫比乌斯反演都是求和,但是这个是求积,要想一想怎么才能找到乘积与求和的关系(当然不是把累乘变成累加),然后可以考虑到每个斐波那契数出现了多少次,出现次数累加起来作为这个斐波那契数的幂,似乎就可以做了

开始推式子啦:

\[\begin{aligned} \prod_{i=1}^n\prod_{j=1}^mF_{gcd(i,j)}&=\prod_{k=1}^{min(n,m)}F_k^{\sum_{i=1}^n\sum_{j=1}^m[gcd(i,j)==k]} \end{aligned} \]

上面的次幂是老套路了,就不细写了,反正肯定是往莫比乌斯反演的那三个套路模型上面去靠,如果不知道的话,可以[看我](莫比乌斯反演常见的三个模型 - 6penny - 博客园 (cnblogs.com))

\[\begin{aligned} \prod_{k=1}^{min(n,m)}F_k^{\sum_{i=1}^n\sum_{j=1}^m[gcd(i,j)==k]}&=\prod_{k=1}^{min(n,m)}F_k^{\sum_{d=1}^{min(n,m)}\lfloor\frac{n}{kd}\rfloor\lfloor\frac{m}{kd}\rfloor\mu(d)}\\ &=\prod_{T=1}^n(\prod_{k|T}F_k^{\mu(\frac{T}{k})})^{\lfloor\frac{n}{T}\rfloor\lfloor\frac{m}{T}\rfloor} \end{aligned} \]

说具体一点就是设\(T=kd\),用\(T\)去换元,把\(\mu\)放到斐波那契里面直接一起处理了

这个式子最后的样子也是老套路了,但是不能直接在筛的时候处理

实现细节

上面说到不能直接在筛的时候将内层求积计算出来,是因为斐波那契不是一个积性函数,所以我们直接在预处理的时候暴力将斐波那契数的\(\mu\)次方算出来

注意因为莫比乌斯函数有可能是\(-1\)所以要求逆元

注意随时随地要取模,血的教训

代码实现

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll M=1e6+10,p=1e9+7;
ll pr[M],cnt,vis[M],mu[M],f[M],mul[M],inv[M];
ll qpow(ll x,ll y){
	ll res=1;
	while(y){
		if(y&1)res=res*x%p;
		x=x*x%p;
		y>>=1;
	}
	return res%p;
}
void init(){
	mu[1]=f[2]=f[1]=mul[1]=mul[0]=1;
	inv[0]=0,inv[1]=1,inv[2]=1;
	for(ll i=3;i<=M-10;i++){
		f[i]=(f[i-1]+f[i-2])%p;
		inv[i]=qpow(f[i],p-2)%p;
	}
	mul[1]=mul[0]=1;
	for(ll i=2;i<=M-10;i++){
		mul[i]=1;//注意不要memset,血的教训
		if(!vis[i]){
			vis[i]=1;
			pr[++cnt]=i;
			mu[i]=-1;
		}
		for(ll j=1;j<=cnt&&pr[j]*i<=M-10;j++){
			vis[pr[j]*i]=1;
			if(i%pr[j]==0){
				mu[i*pr[j]]=0;
				break;
			}else{
				mu[i*pr[j]]=-mu[i];
			}
		}
	}
	for(ll i=1;i<=M-10;i++){//暴力求解斐波那契的次幂的累乘
		if(!mu[i])continue;
		for(ll j=i;j<=M-10;j+=i){
			if(mu[i]==1){
				mul[j]=(mul[j]*f[j/i]%p+p)%p;
			}else{
				mul[j]=(mul[j]*inv[j/i]%p+p)%p;
			}
		}
	}
	for(ll i=1;i<=M-10;i++)mul[i]=(mul[i-1]*mul[i]%p+p)%p;
}
ll calc(ll x,ll y){
	ll res=1;
	for(ll l=1,r=0;l<=min(x,y);l=r+1){
		r=min(x/(x/l),y/(y/l));
		res=(res*qpow(mul[r]*qpow(mul[l-1],p-2)%p,(x/l)*(y/l))%p)%p;
        //注意到这里就是最后的公式,因为是区间前缀积计算,所以除法得到区间积的话要用逆元
        //求幂数的时候不要写着写着出来个取模,血的教训
	}
	return res%p;
}
void solve(){
	ll n,m;
	scanf("%lld%lld",&n,&m);
	printf("%lld\n",calc(n,m)%p);
}
int main(){
	ll T;
	scanf("%lld",&T);
	init();
	while(T--)solve();
	return 0;
}

总结

有一个套路是可以积累下来的:找到累乘与累加的关系,一般情况下(估计是针对莫比乌斯反演),累加是作为累乘的某个项的幂数

标签:表格,题解,ll,莫比,mu,反演,SDOI2017,prod,sum
From: https://www.cnblogs.com/Zhangrx-/p/17396773.html

相关文章

  • 问题解决:TNS-12543: TNS:destination host unreachable
    环境:11.2.0.3ADG(db11g\db11gadg\db11gcas)在自己先前克隆后的环境互相tnsping报错。tnsping本机ok,tnsping其他机器均报错:[oracle@db11g~]$tnspingjingyuTNSPingUtilityforLinux:Version11.2.0.3.0-Productionon13-MAY-202308:09:11Copyright(c)1997,......
  • cf 870div2 abcd题解
    A题,先假设一个res从0开始,判断说谎人的个数用ans表示,如果res==ans则假设成立#include<iostream>usingnamespacestd;typedeflonglongll;typedefunsignedlonglongull;typedefdoubledb;typedefpair<int,int>PII;constllINF=0x3f3f3f3f;constintN=1e4+10;in......
  • 题解 ABC239F【Construct Highway】
    翻译:给定\(n,m\)和度数数组\(\{d_i\}\),再给你\(m\)条边,请构造一棵\(n\)点的树包含这\(m\)条边,且第\(i\)个点的度数为\(d_i\),或者判断无解。显然,若\(\sumd_i\ne2(n-1)\),则无解。然后对于输入的每条边,使用并查集维护,再求出在这\(m\)条边的基础上每个点还需要多......
  • vi基本入门操作,Ubuntu中vi方向键乱码问题解决方案?
    一、vi基本操作语法:vi+文本名例如创建一个名为text的文本文件进入后先敲击键盘"I"(看个人习惯,敲“a”也是一样的结果,大小写都行),进入插入模式,即可正常输入如果要敲错了内容,和Windows一样,用backspace来删除,也可以用delete键,问题在于用delete键只能删除选中部分的内容,且仅能选......
  • 2023市北区程序设计竞赛题解
    1.分糖果原题: 解题思路:这道题类似于辗转相除法,这道题是辗转相减,每次取余数,如果整除,直接计算答案,并退出,否则继续取余 AC代码:#include<bits/stdc++.h>#definelllonglongusingnamespacestd;intmain(){ lla,b,ans=0;cin>>a>>b; while(a!=b){ if(a<b)swap(a,b......
  • 使用Latex制作表格方法总结
    1.前言最近又开始写论文,记录一下使用Latex制作表格的方法2.不同类型表格制作2.1最基本的无线表格:tabbing利用制表位进行表格的排版,但是不会出现表线,另外这个环境对于制表位比较灵活,需要考虑很多因素(制表位的相对位置)才能制作出一个精美的表格.一般来说不是很常用.......
  • 洛谷 P4544 [USACO10NOV]Buying Feed G - 题解
    https://www.luogu.com.cn/problem/P4544感觉是很没意思的DP+DS优化,以前做过几道更难的题:https://codeforces.com/contest/1788/problem/Ehttps://atcoder.jp/contests/abc288/tasks/abc288_f这种题只要是让我写总是能把代码整的伤痕累累(逃第一眼:我艹不就是一个sbDP吗......
  • vika维格表更名为vika维格云:再小的个体都有自己的多维表格
    怀着激动的心情,在此向各位关心我们的用户与伙伴宣布: vika维格表已正式更名为「vika维格云」。 顾名思义,「多维表格」进化成了「多维表格云」。这个新名字代表着我们的产品已经发展到了一个全新的阶段。我们将以此为契机,为用户带来更好、更多面的体验与服务,更好实现我们的......
  • 模拟测试题解
    题目链接:https://vjudge.csgrandeur.cn/contest/557480AOJ维护中计算a+b(0<=a,b<=10)。点击查看代码#include<iostream>usingnamespacestd;intmain(){inta,b;cin>>a>>b;cout<<a+b;return0;}B不支持python队列报数,直接模拟即可。点击查看......
  • python导出postgresql中的一个表到本地csv表格
     代码如下修改xxx即可:conn=psycopg2.connect(host=DB_SERVICES,user=DB_USERNAME,password=DB_PWD,database=DB_NAME)cur=conn.cursor(cursor_factory=psycopg2.extras.DictCursor)sql=f"select*fromxxx.xxx"cur.execute(sql)res=cur.fetchall()pand......