寒蝉凄切,对长亭晚,骤雨初歇。都门帐饮无绪,留恋处,兰舟催发。执手相看泪眼,竟无语凝噎。念去去,千里烟波,暮霭沉沉楚天阔。
多情自古伤离别,更那堪,冷落清秋节!今宵酒醒何处?杨柳岸,晓风残月。此去经年,应是良辰好景虚设。便纵有千种风情,更与何人说!
——宋·柳永《雨霖铃》
字虽好,只是柳永伤感。执手相看泪眼,竟无语凝噎。太不合此情此景。
——爱新觉罗氏胤禛
西施与范蠡泛舟而去……不对,场景不对,咳咳。在甄嬛前往蓬莱洲之前,她与皇上在碧桐书院告别。为了这可能会长达数月的离别,两个人都似乎有很多话要对对方说,却都无语凝噎。这时,皇上突然发话:“嬛嬛啊,既然你我都说不出话来,那这时间也不好打发,我们来数三角形吧。”为了满足皇上突发而来的童趣,甄嬛欣然陪同了。可这……纸上是一张n*m的格子方阵,即有(n+1)*(m+1)个格点。每个格子都是边长为1的正方形。而他们要数的,则是任取3个格点作为三角形的顶点所形成的直角三角形且该三角形面积为s/2的个数。甄嬛数的头都晕了,她现在只想知道满足条件的三角形个数 mod (10^9+7)
输入格式:
第一行3个正整数n,m,s, 意义如题
输出格式:
仅一个整数,为甄嬛与满足条件的三角形个数 mod (10^9+7)
样例输入:
1 1 1
样例输出:
4
数据范围:
对于10%的数据:n<=10
对于另外40%的数据:s为质数
对于100%的数据:1<=n,m,s<=10^8
时间限制:
1S
空间限制:
128M
这题刚开始实在是想的太简单了,习惯性认为直角边都在网格上,其实不然,还有不在网格上的情况没有发现.
先说直角边在网格上的情况:
由于他是直角三角形,肯定被包含在一个合法矩形内,而每个矩形都包含了4个这种三角形,所以,我们枚举矩形的长宽a,b,对于每一组a,b,我们可以计算出这种情况中的直角三角形的总数.
总数为max(0,n-a+1)*max(0,m-b+1)*4+max(0,m-a+1)*max(0,n-b+1)*4.
再说直角边不在网格上的情况:
对于这一类直角三角形,我们总能在它边上找到两个相似三角形,如下图:
三角形abc边上总有两个相似三角形.我们设相似比为k,且k>=1.
在上图中,我们要知道a,b,k分别是多少,可以通过枚举的方法实现.
由于:AB*BC/2=S/2,则根号(a*a+b*b)*根号(ka*ka+kb*kb)=S,化简得k(a*a+b*b)=S.
由于S在1e8范围内,我们可以枚举a,b,用根号S*根号S的时间(其实远远不到).
由于我们要保证k>=1,所以a*a+b*b<=S.
而比例系数并不一定是整数,整数的应该是a,b,ka,kb,所以不能掉下这个坑啊.
在上图中,整个三角形的横向长度为la=a+kb,纵向长度为lb=max(b,ka);
所以这一种情况中,合法三角形数量为max(0,n-la+1)*max(0,m-lb+1).
由于可以旋转,即横向长度和纵向长度是相对的,所以可以将la和lb互换.
这种情况中,合法三角形数量为max(0,n-la+1)*max(0,m-lb+1).
又由于可翻转性和对称性,同一个形状的三角形(不考虑横纵向)在同一个矩形内可以算4次,即
合法三角形数量为max(0,n-la+1)*max(0,m-lb+1)*4+max(0,n-la+1)*max(0,m-lb+1)*4.
但是需要注意的是,当a*a+b*b=s的时候,说明k=1,即两个相似三角形全等.
此时,我们枚举的这个直角三角形对于横纵向其实是同样的情况(即不存在横纵向之分,或者说,在横向统计和纵向统计中都会统计到这一种三角形),所以这种情况
合法三角形数量为(max(0,n-la+1)*max(0,m-lb+1)*4+max(0,n-la+1)*max(0,m-lb+1)*4)/2.
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<iostream> 5 #include<cmath> 6 #define LL long long 7 using namespace std; 8 const int TT=1000000007; 9 int n,m,s,cnt,fac[20005]; 10 LL ans,c1,c2,la,lb; 11 int main(){ 12 cin>>n>>m>>s; cnt=0; ans=0; 13 for (int i=1; i<=sqrt(s); i++) if (s%i==0) fac[++cnt]=i; 14 for (int i=1; i<=cnt; i++){ 15 c1=n-fac[i]+1,c2=m-(s/fac[i])+1; 16 if (c1>0&&c2>0) ans=(ans+(LL)c1*c2)%TT; 17 if (fac[i]*fac[i]==s) continue; 18 c1=m-fac[i]+1,c2=n-(s/fac[i])+1; 19 if (c1>0&&c2>0) ans=(ans+(LL)c1*c2)%TT; 20 } 21 ans*=4; ans%=TT; 22 for (LL a=1; a*a<=s; a++) 23 for (LL b=1; a*a+b*b<=s; b++){ 24 LL t=a*a+b*b; 25 if ((s*a)%t==0&&(s*b)%t==0){ 26 la=a+(s*b)/t,lb=max((s*a)/t,b); 27 c1=max(0LL,n-la+1),c2=max(0LL,m-lb+1); 28 if (t==s) ans+=c1*c2*2; else ans+=c1*c2*4; 29 c1=max(0LL,m-la+1),c2=max(0LL,n-lb+1); 30 if (t==s) ans+=c1*c2*2; else ans+=c1*c2*4; 31 ans%=TT; 32 } 33 } 34 printf("%lld",(ans+TT)%TT); 35 return 0; 36 }