We have a stick with infinite length. Now we want to cut 3 sub-sticks with length x, y, z which is not large than L to form a right triangle. With unknown reasons we assume that x, y, z are all integers and satisfy that x, y, z are all co-primed each other. We want to know how many right triangles are there exist under our constraints
Input
The first line of input is an integer T (T<=5) indicating the number of test cases.
Each case contains a single integer L (L<=1,000,000,000,000).
Output
For each test case output a single integer in one line, indicating the number of right triangles.
Sample Input
1
5
Sample Output
1
Hint
In our test case, we could find a right triangle (3,4,5) which satisfy 3,4,5<=5 and gcd(3,4)=1,gcd(3,5)=1,gcd(4,5)=1.
如果满足构成指教三角形,则有:
使得
先在就从原来的三元组去找二元组即可,
我们看两两互质的条件是什么: m2−n2 和 2nm 互质,则 gcd(m2−n2,2nm)=1 ,
因为 m2−n2=(m−n)2+2nm
所以即只要 gcd((m−n)2,2nm)=1 ,进一步即
gcd(n2+m2,2nm)=1得出的结论同上
现在看
gcd(m2+n2,m2−n2)=1
,等价于
化为
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#define N 1000005
using namespace std;
bool p[N];
int prime[N];
int phi[N];
int k=0;
void init()//晒出1000000内的素数和欧拉函数
{
for(int i=1;i<N;i++)
phi[i]=i;
for(int i=2;i<N;i++)
{
if(!p[i])
{
prime[k++]=i;
for(int j=i;j<N;j+=i)
{
p[j]=true;
phi[j]-=phi[j]/i;
}
}
}
}
int fac[20];
int cnt;
int get(int limit,int x)//1到limit范围和x互质的数量,用容斥
{
int cnt=0;
for(int i=0;prime[i]*prime[i]<=x;i++)
{
if(x%prime[i]==0)
{
fac[cnt++]=prime[i];
while(x%prime[i]==0)
x/=prime[i];
}
if(x==1)
break;
}
if(x>1)
fac[cnt++]=x;
/*cout<<cnt<<endl;
for(int i=0;i<cnt;i++)
cout<<fac[i]<<" ";
cout<<endl;*/
int ans=0;
for(int s=1;s<(1<<cnt);s++)
{
int mui=1;
int num=0;
for(int i=0;i<cnt;i++)
{
if((1<<i)&s)
{
mui*=fac[i];
num++;
}
}
//cout<<"mil:"<<mui<<endl;
//cout<<limit/mui<<endl;
if(num&1)
ans+=limit/mui;
else
ans-=limit/mui;
}
return limit-ans;
}
long long work(long long L)
{
int up=(int)sqrt(L);
long long ans=0;
for(int m=2;m<=up;m++)//枚举m
{
int maxx=(int)sqrt(L-(double)m*m);相应的n的最大的取值
if(m&1)如果m为奇数,偶数n且n与m互质的
{
if(m<=maxx)
ans+=get(m/2,m);
else
ans+=get(maxx/2,m);
}
else
{
if(m<=maxx)
ans+=phi[m];//这个情况下直接去欧拉函数值
else
ans+=get(maxx,m);
}
}
return ans;
}
int main()
{
init();
int t;
long long L;
//cout<<"ans:"<<get(80,80);
scanf("%d",&t);
while(t--)
{
scanf("%lld",&L);
printf("%lld\n",work(L));
}
return 0;
}