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 }
View Code

 

 
posted @ 2015-09-21 21:55  yanzx6  阅读(356)  评论(0编辑  收藏  举报