AC思路
求满足x1*x2+y1*y2<=L
的四元组的组合数。
可以做一下分解:
a=x1*x2, b=y1*y2 (1)
a+b <= L (2)
- 先来分析(1)。 a=x1*x2,(x1,x2) 的选法的个数其实就是 a 的约数(即因数)的个数。比如
6=1*6=2*3=3*2=6*1
,四个因数,一共就有(1,6),(2,3),(3,2),(6,1)四种选择。
设f(x)即为数x的因数的个数,可以先预处理出所有1-n范围内每一个数的因数的个数。 - 进行(2)式的分析。x1,x2,y1,y2都是正整数,那么a,b也是正整数。要满足 a+b<=L,那么a的范围就是
[1,n-1]
(因为b>=1),b的范围就是[1,n-a]
。
满足a+b<=L, 对于任意一个a,b,所有满足条件的四元组的选法就是f(a)*f(b)。再结合范围推出公式。
#include<iostream>
#include<cstdio>
using namespace std;
typedef long long ll;
const int N = 1050000;
int f[N]; //存储某个数i的因数个数
int n;
ll s[N];
int main()
{
scanf("%d", &n);
//初始化因数个数
for(int i = 1; i <= n; i ++) //对于每一个数
{
for(int j = 1; j <= i/j; j ++)
{
if(i % j == 0)
{
f[i] ++;
if(i/j != j)
f[i] ++;
}
}
}
//初始化前缀和
for(int i = 1; i <= n; i ++)
s[i] = s[i-1] + f[i];
//计算结果
ll cnt = 0;
for(int a = 1; a <= n-1; a ++) //满足a+b<=n
{
cnt += (ll)f[a]*s[n-a];
}
printf("%lld",cnt);
return 0;
}