无知者无畏。|

Oier_szc

园龄:2年1个月粉丝:4关注:4

2024-02-07 22:29阅读: 8评论: 0推荐: 0

洛谷P3455 笔记

传送门

又是一道看了tj的题。

题意

t 次询问,每次询问给定 nmk ,求 i=1nj=1m[gcd(i,j)=k]

1t5×1041kn , m5×104

正文

k 扔到上界去,记原式变为 i=1nkj=1mk[gcd(i,j)=1]

然后利用莫比乌斯函数性质,把等于 1 的判断去掉,得 i=1nkj=1mkd|gcd(i,j)μ(d)

接着把 d 扔到前面去,把整除的条件去掉,记 r=min(nkmk) ,得 d=1ri=1nkdj=1mkdμ(d)

最后一步很显然,μ(d) 放到前面,得到最后的柿子: d=1rμ(d)nkdmkd

这个时候思路很显然了。线性筛筛出 15×104 内的所有 μ(i) 并做一个前缀和,然后就可以整除分块了。

code

//writer:Oier_szc
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+5,INF=2e9,mod=1e9+7;
int t,n,a,b,d;
int f[N],qzh[N];
int primes[N],st[N],len=0;
void xxs()
{
f[1]=1;
for(int i=2;i<=5e4;++i)
{
if(!st[i]) primes[++len]=i,f[i]=-1;
for(int j=1;j<=len&&primes[j]<=5e4/i;++j)
{
st[i*primes[j]]=true;
if(i%primes[j]==0)
{
f[i*primes[j]]=0;
break;
}
else f[i*primes[j]]=-f[i];
}
}
for(int i=1;i<=5e4;++i) qzh[i]=qzh[i-1]+f[i];
}
signed main()
{
xxs();
scanf("%lld",&t);
while(t--)
{
scanf("%lld%lld%lld",&a,&b,&d);
a/=d,b/=d;
n=min(a,b);
int ans=0;
for(int l=1,r;l<=n;l=r+1)
{
r=min(a/(a/l),b/(b/l));
ans+=(qzh[r]-qzh[l-1])*(a/l)*(b/l);
}
printf("%lld\n",ans);
}
return 0;
}

总结一下,可以发现这道题推柿子的技巧在于将难以处理的判断条件用一些转换去掉,得到最终柿子后又用到了线性筛和整除分块的技巧以降低复杂度。

本文作者:StevenZC

本文链接:https://www.cnblogs.com/StevenZC/p/18011419

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Oier_szc  阅读(8)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起