出现正方形顶点都在格点上的情况:
设x,y。比如x=0,y=1表示的就是边长为1的正方形,x=0,y=2表示边长为2的正方形,x=1,y=2表示边长为根号5的正方形,x=1,y=3表示的是边长为根号9的正方形。那么特定的x,y可以表示一种正方形。
经过观察,x+y是刚好放下这个正方形所要的格子的边长。x*x+y*y是这个正方形的面积。
再观察,假设格子大小为n,m(n<m),设一种正方形边长为L;
L=1时,这种正方形的个数=n*m;
L=2,个数=(n-1)*(m-1);
L=3,个数=(n-2)*(m-2);
L=n,个数=1*(m-n+1);
就可以直接求x+y=L的正方形的个数。
在x+y=L的各种正方形中,满足条件的正方形类型有x1=0,y1=L; x2=1,y2=L-1……x'=L-1,y'=1;每一种都是(n-L+1)*(m-L+1)个。
这些正方形面积加起来是:( 0*0+L*L )+( 1*1+(L-1)*(L-1) )+......+( (L-1)*(L-1)+1*1 );
再观察一下,发现是两个平方前缀和想加。。。不写了,看代码就会知道的。
#include<cstdio>
#include<cstring>
typedef long long ll;
const int mod=1e9+7;
int t;
ll n,m;
ll sum[10005];
ll num(int i){
return (n-i+1)*(m-i+1)%mod;
}
ll area(int i){
return (sum[i-1]+sum[i])%mod;
}
int main()
{
sum[1]=1;
for(int i=2;i<=10001;i++){
sum[i]=(sum[i-1]+i*i%mod)%mod;
}
scanf("%d",&t);
while(t--){
scanf("%lld%lld",&n,&m);
int limit=n;
if(m<n) limit=m;
ll ans1=0,ans2=0;
for(int i=1;i<=limit;i++){
ans1=(ans1+num(i)*i%mod)%mod;
ans2=(ans2+num(i)*area(i)%mod)%mod;
}
printf("%lld %lld\n",ans1,ans2);
}
return 0;
}