这个题如果不看题解,是肯定没办法AC的。
http://www.cnblogs.com/scau20110726/archive/2013/01/18/2866957.html
大致说一下方法。
a=s*t
b=(s*s-t*t)/2
c=(s*s+t*t)/2
a*a+b*b==c*c
其中,s>t>=1且互质并皆为奇数。据此可以枚举s,t,另外注意利用a,b<c<=N缩小枚举范围。
这是素勾股数的构造办法,其余勾股数可以通过倍增来找到。
#include <iostream> #include <cstdlib> #include <cstdio> #include <cstring> #include <vector> #include <cmath> #include <algorithm> #define MAXN 1000005 #define MOD 1000000007 #define INF 2139062143 #define ll long long using namespace std; ll gcd(ll a,ll b) { return !a?b:gcd(b%a,a); } bool vis[MAXN]; int main() { int N; while(scanf("%d",&N)!=EOF) { memset(vis,0,sizeof(vis)); int m=sqrt(N*1.0); int cnt1=0,cnt2=0; for(ll t=1; t<=m; t+=2) for(ll s=t+2; s*t<=N; s+=2) { if(gcd(s,t)==1) { ll a=s*t,b=(s*s-t*t)/2,c=(s*s+t*t)/2; if(c<=N) { cnt1++; vis[a]=vis[b]=vis[c]=true; for(int l=2;l*c<=N;++l) vis[l*a]=vis[l*b]=vis[l*c]=true; } } } for(int i=1;i<=N;++i) if(!vis[i]) cnt2++; printf("%d %d\n",cnt1,cnt2); } return 0; }