BZOJ5332: [Sdoi2018]旧试题(莫比乌斯反演)
时光匆匆,转眼间又是一年寒暑……
这是小 Q 同学第二次参加省队选拔赛。
今年,小 Q 痛定思痛,不再冒险偷取试题,而是通过练习旧 试题提升个人实力。可是旧试题太多了,小 Q 没日没夜地做题,却看不到前方的光明在哪里。
一天,因做题过度而疲惫入睡的小 Q 梦到自己在考场上遇到了一道好像做过的题目,却怎么也想不 起曾经自己是怎么解决它的,直到醒来还心有余悸。
小 Q 眉头一皱,感觉事情不妙,于是他找到了你,希望你能教他解决这道题目。小 Q 依稀记得题目 要计算如下表达式的值
$({\sum_{i=1}^{A}}{\sum_{j=1}^{B}}{\sum_{k=1}^{C}}d(ijk))mod(10^9+7)$
其中 d(ijk) 表示 ijk 的约数个数。
Input
第一行包含一个正整数 T,表示有 T 组测试数据。 接下来 T 行,每行描述一组测试数据,包含三个整数 A, B 和 C,含义见题目描述。
Output
对于每组测试数据,输出一行,包含一个整数,表示所求表达式的值。
解题思路:
极限卡常题,具体卡常的方法主要是使用vector代替链式前向星,如果还过不去,还是看看dalao们的博客吧。
这里主要讲算法。
首先是喜闻乐见的莫比乌斯反演,三个$\sum$有点中暑,慢慢推吧其实都差不多。
不妨设$A\leq B\leq C$,则:
$Ans={\sum_{i=1}^{A}}{\sum_{j=1}^{B}}{\sum_{k=1}^{C}}d(ijk)$
$={\sum_{i=1}^{A}}{\sum_{x|i}}{\sum_{j=1}^{B}}{\sum_{y|j}}{\sum_{k=1}^{C}}{\sum_{z|k}}{\varepsilon(gcd(x,y))}{\varepsilon(gcd(y,z))}{\varepsilon(gcd(x,z))}$
$={\sum_{x=1}^{A}}{\sum_{x|i}^{A}}{\sum_{y=1}^{B}}{\sum_{y|j}^{B}}{\sum_{z=1}^{C}}{\sum_{z|k}^{C}}{\varepsilon(gcd(x,y))}{\varepsilon(gcd(y,z))}{\varepsilon(gcd(x,z))}$
$={\sum_{x=1}^{A}}{\sum_{y=1}^{B}}{\sum_{z=1}^{C}}{\left\lfloor{\frac{A}{x}}\right\rfloor}{\left\lfloor{\frac{B}{y}}\right\rfloor}{\left\lfloor{\frac{C}{z}}\right\rfloor}{\varepsilon(gcd(x,y))}{\varepsilon(gcd(y,z))}{\varepsilon(gcd(x,z))}$
$={\sum_{x=1}^{A}}{\sum_{y=1}^{B}}{\sum_{z=1}^{C}}{\left\lfloor{\frac{A}{x}}\right\rfloor}{\left\lfloor{\frac{B}{y}}\right\rfloor}{\left\lfloor{\frac{C}{z}}\right\rfloor}{\sum_{i|gcd(x,y)}}{\sum_{j|gcd(y,z)}}{\sum_{k|gcd(x,z)}}{\mu(i))}{\mu(j))}{\mu(k))}$
$={\sum_{i=1}^{A}}{\sum_{j=1}^{B}}{\sum_{k=1}^{A}}{\mu(x)}{\mu(y)}{\mu(z)}{\sum_{x|lcm(i,k)}}{\sum_{y|lcm(i,j)}}{\sum_{z|lcm(j,k)}}{\left \lfloor {\frac{A}{i}} \right \rfloor}{\left \lfloor {\frac{B}{j}} \right \rfloor}{\left \lfloor {\frac{C}{k}} \right \rfloor}$
将$\mu$不等于0的连边,双向改单向枚举三元环就好了。
代码:
- #include<cstdio>
- #include<vector>
- #include<cstring>
- #include<algorithm>
- typedef long long lnt;
- const int N=;
- const lnt mod=(lnt)(1e9+);
- struct edge{
- int from;
- int to;
- int lcm;
- }ed[N*];
- struct ent{
- int twd;
- int lcm;
- };
- int prime[N];
- int miu[N];
- int ind[N];
- bool vis[N];
- lnt Lcm[N];
- lnt F[][N];
- int cnt;
- std::vector<ent>hd[N];
- int A,B,C;
- void gtp(void)
- {
- miu[]=;
- for(int i=;i<N;i++)
- {
- if(!vis[i])
- {
- prime[++cnt]=i;
- miu[i]=-;
- }
- for(int j=;j<=cnt&&prime[j]*i<N;j++)
- {
- vis[i*prime[j]]=true;
- if(i%prime[j]==)
- break;
- miu[i*prime[j]]=-miu[i];
- }
- }
- return ;
- }
- lnt gcd(lnt x,lnt y)
- {
- if(!y)
- return x;
- return gcd(y,x%y);
- }
- int main()
- {
- int T;
- gtp();
- scanf("%d",&T);
- while(T--)
- {
- int a,b,c;
- scanf("%d%d%d",&a,&b,&c);
- A=std::min(a,std::min(b,c));
- C=std::max(a,std::max(b,c));
- B=a+b+c-A-C;
- cnt=;
- for(int i=;i<=C;i++)
- hd[i].clear(),ind[i]=;
- for(int i=;i<=C;i++)
- F[][i]=F[][i]=F[][i]=;
- for(int i=;i<=A;i++)
- for(int j=i;j<=A;j+=i)
- F[][i]+=A/j;
- for(int i=;i<=B;i++)
- for(int j=i;j<=B;j+=i)
- F[][i]+=B/j;
- for(int i=;i<=C;i++)
- for(int j=i;j<=C;j+=i)
- F[][i]+=C/j;
- lnt ans=;
- for(int i=;i<=A;i++)
- if(miu[i])
- ans+=miu[i]*F[][i]*F[][i]*F[][i];
- ans%=mod;
- for(int d=;d<=C;d++)
- {
- for(int i=;i*d<=C;i++)
- {
- if(!miu[i*d])
- continue;
- for(int j=i+;1ll*j*i*d<=C;j++)
- {
- if(miu[j*d]==||gcd(j,i)!=)
- continue;
- int x=i*d,y=j*d,lcm=i*j*d;
- ans+=miu[x]*(F[][y]*F[][lcm]*F[][lcm]+F[][y]*F[][lcm]*F[][lcm]+F[][y]*F[][lcm]*F[][lcm]);
- ans=ans%mod;
- ans+=miu[y]*(F[][x]*F[][lcm]*F[][lcm]+F[][x]*F[][lcm]*F[][lcm]+F[][x]*F[][lcm]*F[][lcm]);
- ans=ans%=mod;
- ind[x]++;
- ind[y]++;
- ed[++cnt]=(edge){x,y,lcm};
- }
- }
- }
- for(int i=;i<=cnt;i++)
- {
- int f=ed[i].from,t=ed[i].to,v=ed[i].lcm;
- if(ind[f]<ind[t]||(ind[f]==ind[t]&&f<t))
- hd[f].push_back((ent){t,v});
- else
- hd[t].push_back((ent){f,v});
- }
- for(int i=;i<=C;i++)
- {
- for(int j=;j<hd[i].size();j++)
- Lcm[hd[i][j].twd]=hd[i][j].lcm;
- for(int j=;j<hd[i].size();j++)
- {
- int a=i,b=hd[i][j].twd;
- for(int k=;k<hd[b].size();k++)
- {
- int c=hd[b][k].twd;;
- int lab=hd[a][j].lcm;
- int lbc=hd[b][k].lcm;
- int lac=Lcm[c];
- if(!lac)
- continue;
- lnt tmp=miu[a]*miu[b]*miu[c];
- lnt ttt=F[][lab]*F[][lbc]*F[][lac]+
- F[][lab]*F[][lac]*F[][lbc]+
- F[][lbc]*F[][lac]*F[][lab]+
- F[][lbc]*F[][lab]*F[][lac]+
- F[][lac]*F[][lab]*F[][lbc]+
- F[][lac]*F[][lbc]*F[][lab];
- ans=(ans+ttt*tmp%mod)%mod;
- }
- }
- for(int j=;j<hd[i].size();j++)
- Lcm[hd[i][j].twd]=;
- }
- printf("%lld\n",(ans%mod+mod)%mod);
- }
- return ;
- }
BZOJ5332: [Sdoi2018]旧试题(莫比乌斯反演)的更多相关文章
- LOJ2565 SDOI2018 旧试题 莫比乌斯反演、三元环计数
传送门 这道题的思路似乎可以给很多同时枚举三个量的反演题目提供一个很好的启发-- 首先有结论:\(d(ijk) = \sum\limits_{x|i}\sum\limits_{y|j}\sum\lim ...
- Bzoj5332: [Sdoi2018]旧试题
国际惯例的题面首先我们进行一些相对显然的数学变化.解释一下第二行的那个变形,如果一个数是ijk的因数,那么它一定能被分解成三部分分别是i,j,k的因数.我们钦定一个质数只能在三部分的一个中出现.如果一 ...
- 【BZOJ5332】[SDOI2018]旧试题(数论,三元环计数)
[BZOJ5332][SDOI2018]旧试题(数论,三元环计数) 题面 BZOJ 洛谷 题解 如果只有一个\(\sum\),那么我们可以枚举每个答案的出现次数. 首先约数个数这个东西很不爽,就搞一搞 ...
- [SDOI2018] 旧试题
推狮子的部分 \[ \sum_{i=1}^A\sum_{j=1}^B\sum_{k=1}^C\sigma(ijk) =\sum_{i=1}^A\sum_{j=1}^B\sum_{k=1}^C\sum_ ...
- P4619 [SDOI2018]旧试题
题目 P4619 [SDOI2018]旧试题 Ps:山东的题目可真(du)好(liu),思维+码量的神仙题 推式 求\(\sum_{i=1}^A\sum_{j=1}^B\sum_{k=1}^Cd(ij ...
- [bzoj 5332][SDOI2018]旧试题
传送门 Description \[ \sum_{i=1}^A\sum_{j=1}^B\sum_{k=1}^Cd(ijk) (\mathrm{mod\:} 10^9+7) \] 其中 \(d(ijk) ...
- sdoi2018旧试题 证明
- BZOJ 5330 Luogu P4607 [SDOI2018]反回文串 (莫比乌斯反演、Pollard Rho算法)
题目链接 (BZOJ) https://www.lydsy.com/JudgeOnline/problem.php?id=5330 (Luogu) https://www.luogu.org/prob ...
- BZOJ_4176_Lucas的数论_杜教筛+莫比乌斯反演
BZOJ_4176_Lucas的数论_杜教筛+莫比乌斯反演 Description 去年的Lucas非常喜欢数论题,但是一年以后的Lucas却不那么喜欢了. 在整理以前的试题时,发现了这样一道题目“求 ...
随机推荐
- linux中的swap
1. 也许你会经常遇到一个经典的swap大小设置问题(比如狗血的面试题). 很多人多会说内存的2倍.. 但是个人认为一般而言 swap 不要设置太大,最好不要超过4G. 2. 进程申请内存不足时,发现 ...
- Navicat for Oracle
1.先解压Navicat for Oracle到任意目录 2.将instantclient-basic-nt-12.1.0.2.0解压到1中目录的instantclient_10_2文件夹下(推荐,可 ...
- 利用中间件 mysql_proxy 完成 mysql 的负载均衡和读写分离
安装 mysql_proxy cd /usr/local/src wget http://mysql.cdpa.nsysu.edu.tw.Downloads/MySQL - ...
- HDU 4937 Lucky Number 搜索
题意: 给你一个数,求在多少种不同的进制下这个数每一位都是3.4.5.6中的一个. 思路: 搜索.枚举这个数在任意进制下的表示,判断是否合法.当数字只有3.4.5.6时,必定有无穷种. 因为数字太大, ...
- hdu 1024 最大m子段和
注:摘的老师写的 最大m子段和问题 以-1 4 -2 3 -2 3为例最大子段和是:6最大2子段和是:4+(3-2+3)=8所以,最大子段和和最大m子段和不一样,不能用比如先求一个最大子段和,从序列中 ...
- 分别改动Cube每一个面的贴图UV(Unity3D开发之十八)
猴子原创.欢迎转载.转载请注明: 转载自Cocos2Der-CSDN,谢谢! 原文地址: http://blog.csdn.net/cocos2der/article/details/46611169 ...
- zend framework获取数据库中枚举类enum的数据并将其转换成数组
在model中建立这种模型,在当中写入获取枚举类的方法 请勿盗版,转载请加上出处http://blog.csdn.net/yanlintao1 class Student extends Zend_D ...
- RvmTranslator7.0-IFC
RvmTranslator7.0-IFC eryar@163.com RvmTranslator can translate the RVM file exported by AVEVA Plant( ...
- Android控件-TabHost(一)
什么是TabHost? TabHost组件的主要功能是可以进行应用程序分类管理,例如:在用户使用windows操作系统的时候,经常见到如图所示的图形界面. TabHost选项卡,说到这个组件, ...
- 在Windows下如何创建虚拟环境(默认情况下)
很多小伙伴平时在使用Python的时候,有的项目需要使用Python2来进行开发,有的项目则是需要Python3来进行开发.当不清楚怎么分开环境的时候,此时两个环境开始打架,彼此傻傻分不清楚.虚拟环境 ...