bzoj2154||洛谷P1829 Crash的数字表格&&JZPTAB && bzoj3309 DZY Loves Math
bzoj2154||洛谷P1829
https://www.lydsy.com/JudgeOnline/problem.php?id=2154
https://www.luogu.org/problemnew/show/P1829
不妨设n<=m
就是求$ans=\sum_{k=1}^m{\frac{1}{k}}\sum_{i=1}^n\sum_{j=1}^m{ij[(i,j)=k]}$
把1/k后面的那一部分提出来,设为f(k),
然后莫比乌斯反演得到f(k)较简易的计算式,代回ans,并化简(过程略)
最后化简出来是$\sum_{k=1}^m{k}\sum_{i=1}^{{\lfloor}\frac{m}{k}{\rfloor}}\mu(i){i^2}g({{\lfloor}\frac{{\lfloor}\frac{n}{k}{\rfloor}}{i}{\rfloor}},{{\lfloor}\frac{{\lfloor}\frac{m}{k}{\rfloor}}{i}{\rfloor}})$
其中$g(x,y)=\frac{(x+1)x(y+1)y}{4}$
可以通过两重的整除分块以O(n)的复杂度计算(第一重枚举n/k,m/k,第二重枚举(n/k)/i,(m/k)/i)
- #pragma GCC optimize(3)
- #include<cstdio>
- #include<algorithm>
- #include<cstring>
- #include<vector>
- using namespace std;
- #define fi first
- #define se second
- #define mp make_pair
- #define pb push_back
- typedef long long ll;
- typedef unsigned long long ull;
- typedef pair<int,int> pii;
- #define md 20101009
- #define N 10000000
- ll prime[N+],len,mu[N+],dd[N+];
- bool nprime[N+];
- ll Mod(ll a,ll b)
- {
- if(a>=) return a%b;
- else if(a%b==) return ;
- else return b+a%b;
- }
- ll G(ll x,ll y)
- {
- return (x+)*x%md*(y+)%md*y%md*%md;
- }
- ll calc(ll n,ll m)
- {
- ll i,j,ans=;
- for(i=;i<=m;i=j+)
- {
- if(n<i) j=min(m,m/(m/i));
- else j=min(m,min(n/(n/i),m/(m/i)));
- ans=Mod(ans+(dd[j]-dd[i-])*G(n/i,m/i),md);
- }
- return ans;
- }
- ll n,m;
- int main()
- {
- ll i,j,ans=;
- mu[]=;
- for(i=;i<=N;i++)
- {
- if(!nprime[i]) prime[++len]=i,mu[i]=-;
- for(j=;j<=len&&i*prime[j]<=N;j++)
- {
- nprime[i*prime[j]]=;
- if(i%prime[j]==) {mu[i*prime[j]]=;break;}
- else mu[i*prime[j]]=-mu[i];
- }
- }
- for(i=;i<=N;i++) dd[i]=dd[i-]+i*i*mu[i];
- scanf("%lld%lld",&n,&m);
- //n=10000000;m=1000;
- if(n>m) swap(n,m);
- for(i=;i<=m;i=j+)
- {
- if(n<i) j=min(m,m/(m/i));
- else j=min(m,min(n/(n/i),m/(m/i)));
- ans=(ans+(i+j)*(j-i+)/*calc(n/i,m/i))%md;
- }
- printf("%lld",ans);
- return ;
- }
额,好像还有一道题面基本一样的题(然而bzoj权限题,不能交),然而是很多组数据,不能每次O(n)算
相关:https://blog.csdn.net/qq_30974369/article/details/79087445
对于这个式子$\sum_{k=1}^m{k}\sum_{i=1}^{{\lfloor}\frac{m}{k}{\rfloor}}\mu(i){i^2}g({{\lfloor}\frac{n}{ik}{\rfloor}},{{\lfloor}\frac{m}{ik}{\rfloor}})$
令T=ik
原式=$\sum_{k=1}^m{k}\sum_{k|T}\mu(\frac{T}{k})(\frac{T}{k})^2g({{\lfloor}\frac{n}{T}{\rfloor}},{{\lfloor}\frac{m}{T}{\rfloor}})$
=$\sum_{T=1}^mg({{\lfloor}\frac{n}{T}{\rfloor}},{{\lfloor}\frac{m}{T}{\rfloor}})\sum_{k|T}k\mu(\frac{T}{k})(\frac{T}{k})^2$
最后从sigma k|T开始那一部分,等于$(id*(\mu\cdot id\cdot id))(T)$
是个积性函数,且是可以线性筛出来的(然而我不会,又去查了题解),将其设为函数h
对于1,h[1]=1
对于一个质数p,h[p]=$1*\mu(p)*p^2+p*\mu(1)*1^2$
对于i%p!=0,h(i*p)=h(i)*h(p)(由于积性)
对于i%p==0,由于h(i*p)拆开后式子中比h(i)多的项的$\mu$值均为0,因此只有对于h(i)中已有的项增加贡献;每一项由$\mu(d)*d^2*(i/d)$变到$\mu(d)*d^2*((i*p)/d)$,因此h(i*p)=h(i)*p
筛出来之后做一下前缀和,这样子每一次询问就可以数论分块根号解决了
- #include<cstdio>
- #include<algorithm>
- #include<cstring>
- #include<vector>
- using namespace std;
- #define fi first
- #define se second
- #define mp make_pair
- #define pb push_back
- typedef long long ll;
- typedef unsigned long long ull;
- typedef pair<int,int> pii;
- #define md 20101009
- #define N 10000000
- ll prime[N+],len,dd[N+];
- bool nprime[N+];
- ll h[N+];
- ll Mod(ll a,ll b)
- {
- if(a>=) return a%b;
- else if(a%b==) return ;
- else return b+a%b;
- }
- ll G(ll x,ll y)
- {
- return (x+)*x%md*(y+)%md*y%md*%md;
- }
- ll n,m;
- int main()
- {
- ll i,j,ans=;
- h[]=;
- for(i=;i<=N;i++)
- {
- if(!nprime[i]) prime[++len]=i,h[i]=Mod(-i*i+i,md);
- for(j=;j<=len&&i*prime[j]<=N;j++)
- {
- nprime[i*prime[j]]=;
- if(i%prime[j]==) {h[i*prime[j]]=h[i]*prime[j]%md;break;}
- else h[i*prime[j]]=h[i]*h[prime[j]]%md;
- }
- }
- for(i=;i<=N;i++) dd[i]=(dd[i-]+h[i])%md;
- scanf("%lld%lld",&n,&m);
- //n=10000000;m=1000;
- if(n>m) swap(n,m);
- for(i=;i<=m;i=j+)
- {
- if(n<i) j=min(m,m/(m/i));
- else j=min(m,min(n/(n/i),m/(m/i)));
- ans=(ans+Mod(dd[j]-dd[i-],md)*G(n/i,m/i))%md;
- }
- printf("%lld",ans);
- return ;
- }
upd181010:
$\sum_{k|T}k\mu(\frac{T}{k})(\frac{T}{k})^2=T\sum_{k|T}\mu(\frac{T}{k})\frac{T}{k}=T\sum_{k|T}\mu(k)k$
这个式子似乎并没有什么用...但是可以记一下,说不定下次就给出最后的那个呢
bzoj3309
https://www.lydsy.com/JudgeOnline/problem.php?id=3309
不妨设a<=b
显然原式=$\sum_{k=1}^bf(k)\sum_{i=1}^{{\lfloor}\frac{b}{k}{\rfloor}}\mu(i){{\lfloor}\frac{a}{ik}{\rfloor}}{{\lfloor}\frac{b}{ik}{\rfloor}}$
用跟上面类似的方法变到$\sum_{T=1}^b{\lfloor}\frac{a}{T}{\rfloor}{\lfloor}\frac{b}{T}{\rfloor}\sum_{k|T}f(k)\mu(\frac{T}{k})$
后面那个不太好筛啊,根本就不会,我又去查题解了。。。
(弃用)如果i%p==0,可以丢掉那些新产生因子的$\mu$,每一项是由$\mu(d)f(i/d)$变到$\mu(d)f(i/d*p)$,显然会加(i的(i/d)中"最大幂指数等于最小质因子的幂指数"的数的$\mu(d)$之和),那个求时依赖的值也可以递推出
(弃用)如果i%p!=0,那么首先会多一些产生贡献的项,这些项是由原来i的任意因子乘上一个p得到的,是$\mu(i/d)f(d)$变到$\mu(i*p/(d*p))f(d*p)=\mu(i/d)f(dp)$,产生的贡献是原来的总和加上一个值(i的因子中"最大幂指数等于最小质因子的幂指数"的数(设为d)的$\mu(i/d)$之和);
筛法的解释:https://blog.csdn.net/phenix_2015/article/details/50799021
这条结论,简单来讲,就是那个函数,只有各个质因子的指数相等的有值((-1)^{质因子数+1}),其他都为0
直接想好像很难想到的样子。。以后记得做这类题要打打表分解分解质因数找找规律
算是A了吧。。。
- #pragma GCC optimize(3)
- #include<cstdio>
- #include<algorithm>
- #include<cstring>
- #include<vector>
- using namespace std;
- #define fi first
- #define se second
- #define mp make_pair
- #define pb push_back
- typedef long long ll;
- typedef unsigned long long ull;
- typedef pair<int,int> pii;
- #define N 10000000
- ll prime[N+],len,mu[N+];
- ll n1[N+],n2[N+],n3[N+],h[N+];
- //分别为最小质因子次数,其他质因子次数,质因子数,函数值
- //n2为-1:第一个质因子;n2为-2:已经失败
- bool nprime[N+];
- ll a,b,ans,T;
- template<class T>
- inline void read(T &x) {
- int f=;x=;char ch=getchar();
- while(ch>''||ch<''){if(ch=='-')f=-;ch=getchar();}
- while(ch>=''&&ch<=''){x*=;x+=(ch-'');ch=getchar();}
- x*=f;
- }
- template<class T>
- inline void write(T x) {
- if(x<) putchar('-'),x=-x;
- if(x>) write(x/);
- putchar(x%+'');
- }
- int main()
- {
- ll i,j;
- mu[]=;
- for(i=;i<=N;i++)
- {
- if(!nprime[i])
- {
- prime[++len]=i;
- mu[i]=-;
- n2[i]=-;
- n3[i]=;
- n1[i]=;
- h[i]=;
- }
- for(j=;j<=len&&i*prime[j]<=N;j++)
- {
- nprime[i*prime[j]]=;
- if(i%prime[j]==)
- {
- mu[i*prime[j]]=;
- n1[i*prime[j]]=n1[i]+;
- n2[i*prime[j]]=n2[i];
- n3[i*prime[j]]=n3[i];
- if(n2[i*prime[j]]==-||n1[i*prime[j]]==n2[i*prime[j]])
- h[i*prime[j]]=(n3[i*prime[j]]%==)?-:;
- else
- h[i*prime[j]]=;
- break;
- }
- else
- {
- mu[i*prime[j]]=-mu[i];
- n1[i*prime[j]]=;
- n2[i*prime[j]]=(n2[i]==-||n2[i]==n1[i])?n1[i]:-;
- n3[i*prime[j]]=n3[i]+;
- if(n2[i*prime[j]]==-||n1[i*prime[j]]==n2[i*prime[j]])
- h[i*prime[j]]=(n3[i*prime[j]]%==)?-:;
- else
- h[i*prime[j]]=;
- }
- }
- }
- //for(i=1;i<=1000;i++) printf("%lld %lld %lld %lld\n",i,h[i],n1[i],n2[i]);
- //return 0;
- for(i=;i<=N;i++) h[i]+=h[i-];
- read(T);
- //T=1000;
- while(T--)
- {
- read(a);read(b);
- //a=7558588;b=9653114;
- if(a==||b==)
- {
- puts("");
- continue;
- }
- if(a>b) swap(a,b);
- ans=;
- for(i=;i<=a;i=j+)
- {
- j=min(a/(a/i),b/(b/i));
- ans+=(a/i)*(b/i)*(h[j]-h[i-]);
- }
- write(ans);putchar('\n');
- }
- return ;
- }
bzoj2154||洛谷P1829 Crash的数字表格&&JZPTAB && bzoj3309 DZY Loves Math的更多相关文章
- 洛谷 - P1829 - Crash的数字表格 - 莫比乌斯反演
求: \(S(n,m)=\sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}lcm(i,j)\) 显然: \(S(n,m)=\sum\limits_{i=1}^{n}\ ...
- 洛谷 P1829 [国家集训队]Crash的数字表格 / JZPTAB 解题报告
[国家集训队]Crash的数字表格 / JZPTAB 题意 求\(\sum\limits_{i=1}^n\sum\limits_{j=1}^mlcm(i,j)\),\(n,m\le 10^7\) 鉴于 ...
- [Luogu P1829] [国家集训队]Crash的数字表格 / JZPTAB (莫比乌斯反演)
题面 传送门:洛咕 Solution 调到自闭,我好菜啊 为了方便讨论,以下式子\(m>=n\) 为了方便书写,以下式子中的除号均为向下取整 我们来颓柿子吧qwq 显然,题目让我们求: \(\l ...
- 题解-[国家集训队]Crash的数字表格 / JZPTAB
题解-[国家集训队]Crash的数字表格 / JZPTAB 前置知识: 莫比乌斯反演 </> [国家集训队]Crash的数字表格 / JZPTAB 单组测试数据,给定 \(n,m\) ,求 ...
- [luogu1829][bzoj2154][国家集训队]Crash的数字表格 / JZPTAB【莫比乌斯反演】
传送门:洛谷,bzoj 题目描述 今天的数学课上,Crash小朋友学习了最小公倍数(Least Common Multiple).对于两个正整数a和b,LCM(a, b)表示能同时整除a和b的最小正整 ...
- 洛谷P1829 [国家集训队]Crash的数字表格 / JZPTAB(莫比乌斯反演)
题目背景 提示:原 P1829 半数集问题 已经迁移至 P1028 数的计算 题目描述 今天的数学课上,Crash小朋友学习了最小公倍数(Least Common Multiple).对于两个正整数a ...
- 洛谷P1829 [国家集训队]Crash的数字表格 / JZPTAB(莫比乌斯反演)
传送门 式子好麻烦orz……大佬好腻害orz->这里 //minamoto #include<iostream> #include<cstdio> #define ll ...
- 洛谷 P1829 [国家集训队]Crash的数字表格 / JZPTAB(莫比乌斯反演)
题意:求$\sum_{i=1}^{n}\sum_{j=1}^{m}lcm(i,j)$. 开始开心(自闭)化简: $\sum_{i=1}^{n}\sum_{j=1}^{m}lcm(i,j)$ =$\su ...
- P1829 [国家集训队]Crash的数字表格 / JZPTAB
推式子太快乐啦!虽然我好蠢而且dummy和maomao好巨(划掉) 思路 莫比乌斯反演的题目 首先这题有\(O(\sqrt n)\)的做法但是我没写咕咕咕 然后就是爆推一波式子 \[ \sum_{i= ...
随机推荐
- 使网页适应UIWebView的宽度
比較简单的做法是:在- (void)webViewDidFinishLoad:这种方法中,改动JavaScript的值: //UIWebViewDelegate - (void)webViewDidF ...
- LeetCode 112 Path Sum(路径和)(BT、DP)(*)
翻译 给定一个二叉树root和一个和sum, 决定这个树是否存在一条从根到叶子的路径使得沿路全部节点的和等于给定的sum. 比如: 给定例如以下二叉树和sum=22. 5 / \ 4 8 / / \ ...
- 图解 servlet 与jsp的关系
Servlet是Java提供的用于开发Web服务器应用程序的一个组件,运行在服务器端,由Servlet容器所管理,用于生成动态的内容.Servlet是平台独立的Java类,编写一个Servlet,实际 ...
- react native 之页面布局
第一章 flexbox 布局 1.flexDirection:'row', 水平 flexDirection:'column',垂直 需要在父元素上设置这种属性才能实现flex. flex:1 会撑 ...
- 各种DP总结
一.数位DP 1.含有或不含某个数“xx”: HDU3555 Bomb HDU2089 不要62 2.满足某些条件,如能整除某个数,或者数位上保持某种特性: HDU3652 B-number Code ...
- 一步一步学Silverlight 2系列(7):全屏模式支持
一步一步学Silverlight 2系列(7):全屏模式支持 概述 Silverlight 2 Beta 1版本发布了,无论从Runtime还是Tools都给我们带来了很多的惊喜,如支持框架语言V ...
- WebStorm配置SVN
下载SVN客户端管理工具TortoiseSVN-1.8.5.25224-x64-svn-1.8.8,选择合适的Windows版本 配置项目目录,对应的VCS为Subversion 设置Subversi ...
- maven实战(6)-- pom.xml的编写
pom.xml中可以编写的东西确实挺多的,经常看到别人写的pom文件中出现了一些没见过plugin或properties等等,不知有何作用,其实很简单,只要参看maven的官方文档即可:http:// ...
- [Selenium] The commonly used validation method
Assert.assertTrue(tmpEl.getAttribute("class").contains("selected"),"The fol ...
- MYSQL数据库学习----MYSQL数据类型
一切数据在计算中都是以二进制形式存储,而8位二进制数就表示1个字节. 通常我们说一种数据类型占多少字节,就是说这种数据类型可以表示多少位的二进制数,同时二进制数可以转换为十进制数,进而得到这种数据类型 ...