51nod1223 分数等式的数量

  1. 【清华冬令营模拟12.28】和与积 (Standard IO)
    Time Limits: 2000 ms Memory Limits: 262144 KB Detailed Limits

Description

这里写图片描述

Input

这里写图片描述

Output
这里写图片描述

Sample Input

2
2
15

Sample Output

0
4

Data Constraint

这里写图片描述

Hint

这里写图片描述

题解

题目要我们求的是 a< b< n 且 a+b|ab的合法的(a,b)的对数

考虑转化,设d=gcd(a,b) ,设 a=a/d,b=b/d d(a+b)|abd2

a+b|abd

gcd(a,b)=1
那么 gcd(a,a+b)=gcd(a+b,a)=1
a+b|d

由于不知道怎么打下取整,下面的除法都当成是套了下取整的吧~
发现d的取值范围是 1—-n/b,那么使得 a+b|d 的取值就有 nb(a+b)

ans=ni=2i1j=1[gcd(i,j)=1]ni(i+j)

当i=j时对gcd不为1所以我们可以补上来,同时我们考虑补上i=1,最后再减掉
下面开始我们的n就是 n便
ans=ni=1ij=1[gcd(i,j)=1]ni(i+j)

f[k]=ni=1ij=1[gcd(i,j)=k]ni(i+j)
那么 ans=f[1]

考虑反演

g[d]=n/dk=1f[kd]
那么 g[d]=n/di=1ij=1ni(i+j)dd

f[d]=n/dk=1μ(k)g[kd]
f[1]=nk=1μ(k)n/ki=1ij=1n(i+j)ikk

其中i+j可以分块

时间复杂度不会算QvQ

贴代码

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#define fo(i,a,b) for(i=a;i<=b;i++)
#define ll long long
using namespace std;

const int maxn=36130;

ll mu[maxn],st[maxn];
bool bz[maxn];
ll i,j,k,l,m,n,x,y,z,o,tp,ans,chu,zi,be,ed;

void yu(){
    mu[1]=1;
    fo(i,2,36123){
        if (bz[i]==false){
            st[++tp]=i; mu[i]=-1;
        }
        fo(j,1,tp){
            if (st[j]*i>36122) break;
            bz[st[j]*i]=true;
            if (i%st[j]==0){
                mu[st[j]*i]=0;
                break;
            }
            mu[st[j]*i]=mu[i]*(-1);
        }
    }
}
int main(){
//  freopen("t3.in","r",stdin);
    scanf("%d",&o);
    yu();
    while (o){
        o--;
        scanf("%d",&n);
        x=trunc(sqrt(n));
        ans=0;
        fo(i,1,x){
            if (mu[i]==0) continue;
            fo(j,1,x/i){
                chu=i*i*j*(j+1);
                be=j+1; zi=n/chu;
                while (be<=j+j){
                    if (zi==0) break;
                    ed=(n/i/i/j)/zi; if (ed>j+j) ed=j+j;
                    ans=ans+mu[i]*zi*(ed-be+1);
                    be=ed+1; chu=i*i*j*be; zi=n/chu;
                }
            }
/*          fo(j,1,x/i) 
                fo(k,1,j) ans+=mu[i]*(n/((j+k)*j*i*i));*/
        }
        printf("%lld\n",ans-n/2);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值