51nod 1165 整边直角三角形的数量
直角三角形,三条边的长度都是整数。给出周长N,求符合条件的三角形数量。
例如:N = 120,共有3种不同的满足条件的直角3角行。分别是:{20,48,52}, {24,45,51}, {30,40,50}。
Input
第1行:一个数T,表示后面用作输入测试的数的数量。(1 <= T <= 50000) 第2 - T + 1行:每行1个数N(12 <= N <= 10^7)。
Output
输出共T行,每行1个对应的数量。
Input示例
2 120 13
Output示例
3 0
题意:问有多少种直角三角形的周长恰好为n
分析:
假设a<b<c
a+b+c=n
a^2+b^2=c^2
c = sqrt(a^2+b^2)
c=n-(a+b)
c^2 = a^2+b^2 = (n-(a+b))^2
a^2+b^2 = n^2 - 2*(a+b)*n + a^2 + b^2 + 2*a*b
2*(a+b)*n = n^2 + 2*a*b
2*n*b - 2*a*b = n^2 - 2*m*a
b = (n^2 - 2*n*a) / (2*n - 2*a)
设 t = n-a
b = (2*(n^2 - n*a) - n^2) / 2*(n-a)
= n - n^2/(2*t)
因为 t = n-a, a < b < c, a+b > c, c < n/2
所以
n-t = a < b = n- n^2/(2*t)
n^2/(2*t) < t
n^2 < 2*t^2
2*t > sqrt(2)*n
t < n
所以 sqrt(2)*n < 2*t < 2*n
所以,只需要找出n的所有因数,把它们个数*2,就是L^2因数的个数
然后枚举每个因数多少个(注意,2*t显然是2的倍数),记一下在那个范围里面的个数,即为答案
下面上代码
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cmath> 5 #include <deque> 6 #include <vector> 7 #include <queue> 8 #include <iostream> 9 #include <algorithm> 10 #include <map> 11 #include <set> 12 #include <ctime> 13 using namespace std; 14 typedef long long LL; 15 typedef double DB; 16 #define For(i, s, t) for(int i = (s); i <= (t); i++) 17 #define Ford(i, s, t) for(int i = (s); i >= (t); i--) 18 #define Rep(i, t) for(int i = (0); i < (t); i++) 19 #define Repn(i, t) for(int i = ((t)-1); i >= (0); i--) 20 #define rep(i, x, t) for(int i = (x); i < (t); i++) 21 #define MIT (2147483647) 22 #define INF (1000000001) 23 #define MLL (1000000000000000001LL) 24 #define sz(x) ((int) (x).size()) 25 #define clr(x, y) memset(x, y, sizeof(x)) 26 #define puf push_front 27 #define pub push_back 28 #define pof pop_front 29 #define pob pop_back 30 #define ft first 31 #define sd second 32 #define mk make_pair 33 inline void SetIO(string Name) { 34 string Input = Name+".in", 35 Output = Name+".out"; 36 freopen(Input.c_str(), "r", stdin), 37 freopen(Output.c_str(), "w", stdout); 38 } 39 40 const int N = 10000010, M = 700010; 41 int Prime[M], Tot; 42 bool Visit[N]; 43 int n; 44 int Factor[M], Num[M], Len; 45 int Left, Right, Answer[N], Ans; 46 47 inline void GetPrime() { 48 For(i, 2, N-1) { 49 if(!Visit[i]) Prime[++Tot] = i; 50 For(j, 1, Tot) { 51 if(i*Prime[j] >= N) break; 52 Visit[i*Prime[j]] = 1; 53 if(!(i%Prime[j])) break; 54 } 55 } 56 } 57 58 inline void Solve(); 59 60 inline void Input() { 61 GetPrime(); 62 63 int TestNumber; 64 scanf("%d", &TestNumber); 65 while(TestNumber--) { 66 scanf("%d", &n); 67 Solve(); 68 } 69 } 70 71 inline void GetFactor(int x) { 72 For(i, 1, Tot) { 73 if(x == 1 || Prime[i] > x) break; 74 if(!(x%Prime[i])) { 75 Len++; 76 Factor[Len] = Prime[i], Num[Len] = 0; 77 while(!(x%Prime[i])) x /= Prime[i], Num[Len]++; 78 } 79 } 80 81 if(x > 1) { 82 Len++; 83 Factor[Len] = x, Num[Len] = 1; 84 } 85 } 86 87 LL Temp; 88 inline void Search(int x, int Val) { 89 if(Left < Val && Val < Right && !(Val%2)) Answer[++Ans] = Val; 90 if(x > Len || Val >= Right) return; 91 92 int Cnt = 1; 93 For(i, 0, Num[x]) { 94 Search(x+1, Val*Cnt); 95 if(Val*Cnt >= Right/Factor[x]) break; 96 Cnt *= Factor[x]; 97 } 98 } 99 100 inline void Solve() { 101 if(n&1) { 102 puts("0"); 103 return; 104 } 105 106 Len = 0; 107 GetFactor(n); 108 For(i, 1, Len) Num[i] <<= 1; 109 110 Ans = 0; 111 Left = n*sqrt(2), Right = 2*n; 112 Search(1, 1); 113 114 sort(Answer+1, Answer+1+Ans); 115 int p = 1; 116 For(i, 2, Ans) 117 if(Answer[p] != Answer[i]) Answer[++p] = Answer[i]; 118 /*For(i, 1, p) { 119 int b = n-n*n/Answer[i]; 120 int a = n-Answer[i]/2; 121 int c = n-a-b; 122 printf("%d %d %d %d\n", Answer[i], a, b, c); 123 }*/ 124 printf("%d\n", p); 125 } 126 127 int main() { 128 #ifndef ONLINE_JUDGE 129 SetIO("1165"); 130 #endif 131 Input(); 132 //printf("%d\n", Tot); 133 //Solve(); 134 return 0; 135 }