通常可以想到直接四个for枚举,但是会超时。就算只用三个for也很危险。可以用打表的方法将时间复杂度降到O(n^2),注意到x1,x2,x3,x4的取值区间是关于零对称的,因此可以只考虑正整数部分,洗后答案乘以16即为正确答案。记得去年蓝桥杯也有一个类似的题。
AC代码:
#include<cstdio> #include<cstring> const int maxn=2e6+5; int hash[maxn]; int solve(int a,int b,int c,int d){ memset(hash,0,sizeof(hash)); for(int i=1;i<=100;++i) for(int j=1;j<=100;++j){ hash[a*i*i+b*j*j+1000000]++; } int sum=0; for(int i=1;i<=100;++i) for(int j=1;j<=100;++j){ sum+=hash[1000000-(i*i*c+j*j*d)]; } return sum*16; //乘以16是因为只处理了正数部分,负数部分也要处理 } int main(){ int a,b,c,d; while(scanf("%d%d%d%d",&a,&b,&c,&d)!=EOF){ printf("%d\n",solve(a,b,c,d)); } return 0; }
如有不当之处欢迎指出!