版权声明:作为一个蒟蒻,转载时请通知我这个蒟蒻 https://blog.csdn.net/zyszlb2003/article/details/89682024
欢迎大家访问我的老师的OJ———caioj.cn
前情提要
建议先去看看Zap,数据加强了,但思路较为简单。
题面描述
思路
与Zap不同的就是多了
注意:2,3和3,2是一种情况
那么我们就要去重了。
设 表示满足 且 的二元组有多少对。
由于
设 表示满足 并且 互质的二元组有多少对。
由于
通过交换,我们可以得到 ,因为 中, , ,且 与 互质, 都被选了两次(仅在 这个范围中能够互相交换,,可以画图细细感受),对于每个 ,根据欧拉函数的定义,这样的 都有 个。
所以我们要完成去重的话,我们要在Zap原答案上减去
特别地,这道题的伪欧拉 ,因为 !
分块求解即可。
就为此题答案。
AC code
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#define ll long long
#define gc getchar()
using namespace std;
inline void qr(int &x)
{
x=0;int f=1;char c=gc;
while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc;}
while(c>='0'&&c<='9'){x=x*10+(c^48);c=gc;}
x*=f;
}
void qw(ll x)
{
if(x/10)qw(x/10);
putchar(x%10+48);
}
const int N=1e4+10;
const int inf=1e4;
const int M=1500;
int prime[M],miu[N],m,phi[N];bool v[N];
inline void g_p()
{
m=0;memset(v,false,sizeof(v));miu[1]=1;phi[1]=1;
for(int i=2;i<=inf;i++)
{
if(!v[i])prime[++m]=i,miu[i]=-1,phi[i]=i-1;
for(int j=1;j<=m&&i*prime[j]<=inf;j++)
{
v[i*prime[j]]=1;
if(i%prime[j]==0)
{
miu[i*prime[j]]=0;
phi[i*prime[j]]=phi[i]*prime[j];
break;
}
else miu[i*prime[j]]=-miu[i],phi[i*prime[j]]=phi[i]*(prime[j]-1);
}
}
}
inline void gcd_miu()
{
int a,b,k;qr(a),qr(a),qr(b),qr(b),qr(k);
a/=k,b/=k;if(a>b)swap(a,b);ll ans=0;
for(int x=1,gx;x<=a;x=gx+1)
{
gx=min(a/(a/x),b/(b/x));
ans+=(ll)(miu[gx]-miu[x-1])*(a/x)*(b/x);
}
ans-=phi[a];
qw(ans);puts("");
}
void solve()
{
for(int i=2;i<=inf;i++)miu[i]+=miu[i-1];
for(int i=3;i<=inf;i++)phi[i]+=phi[i-1];
int t;qr(t);while(t--)gcd_miu();
}
int main()
{
g_p();
solve();
return 0;
}