• 【题解】无语凝噎


    题目

    测试链接:咕咕咕

    题目背景

    寒蝉凄切,对长亭晚,骤雨初歇。都门帐饮无绪,留恋处,兰舟催发。执手相看泪眼,竟无语凝噎。念去去,千里烟波,暮霭沉沉楚天阔。
    多情自古伤离别,更那堪,冷落清秋节!今宵酒醒何处?杨柳岸,晓风残月。 此去经年,应是良辰好景虚设。便纵有千种风情,更与何人说! ——宋·柳永《雨霖铃》

    字虽好,只是柳永伤感。执手相看泪眼,竟无语凝噎。太不合此情此景。 ——爱新觉罗氏胤禛

    题目描述

    西施与范蠡泛舟而去……不对,场景不对,咳咳。在甄嬛前往蓬莱洲之前,她与皇上在碧桐书院告别。为了这可能会长达数月的离别,两个人都似乎有很多话要对对方说,却都无语凝噎。

    这时,皇上突然发话:「嬛嬛啊,既然你我都说不出话来,那这时间也不好打发,我们来数三角形吧。」为了满足皇上突发而来的童趣,甄嬛欣然陪同了。可这……

    纸上是一张 (n imes m) 的格子方阵,即有 ((n+1) imes (m+1)) 个格点。每个格子都是边长为 (1) 的正方形。而他们要数的,则是任取 (3) 个格点作为三角形的顶点所形成的 直角三角形 且该三角形面积为 (dfrac{s}{2}) 的个数。甄嬛数得头都晕了,她现在只想知道满足条件的三角形个数 (mod{10^9+7})

    输入格式

    第一行 (3) 个正整数 (n)(m)(s),意义如题。

    输出格式

    仅一个整数,为满足条件的三角形个数 (mod{10^9+7})

    评测限制

    源程序文件名为 wordless.*,其中 * 为所用语言的源程序拓展名。

    wordless.in 读入,输出至 wordless.out 中。

    评测时间限制 (1000 extrm{ms}),空间限制 (128 extrm{MiB})

    数据范围

    • 对于 (10\%) 的数据,(nle 10)
    • 对于另外 (40\%) 的数据,(s) 为质数;
    • 对于 (100\%) 的数据,(1le n,m,sle 10^8)

    分析

    题目大意是说,给你一个 (n imes m) 的点阵,求出所有由格点作为顶点的直角三角形总数。

    本题的难点在于,平面格点上不一定只有直角边平行于坐标轴的直角三角形,还有「斜着」的。如何统计这类三角形是重中之重。

    (10 exttt{pts})

    枚举所有组合,检查是否合法即可。

    (50 exttt{pts})

    这种情况比较特别。其实可以分成两类

    平着的三角形

    显然,即边长只能是一个为 (1),另一个为 (s)。虽然这并没有什么大作用。

    斜着的三角形

    这就会比一般情况简单很多,因为只有可能是边长为 (sqrt{s})等腰直角三角形,易证。

    所以,我们只要考虑如何才能统计等腰直角三角形的数量即可。

    仿照上面,我们惊奇地发现了两个全等三角形:
    t6cV6e.png
    我们利用这一点,把这个等腰直角三角形放进一个长方形内,也有 (4) 种方案。

    这样,这档分就可以了。

    (100 exttt{pts})

    其实,这个图就是我们完成的关键。我们很容易证明,一组等腰三角形必然对应着一个 唯一的 边平行于坐标轴的最小外界长方形。

    这个「一组」可能是 (4) 个,也有可能是 (2) 个,取决于这个等腰三角形的方向。如果两条直角边正好与坐标轴构成了 (45^{circ}) 还等腰就只有俩。

    而这个长方形的大小,就需要外面那对 相似三角形 来确定。因为并不一定等腰,所以我们并不能直接得到相似比。


    我们设(上面那个图)

    [large{AB=a,AC=b, frac{ riangle CDE}{ riangle BAC}=k} ]

    则易得

    [large{CD=ka,DE=kb} ]

    不妨设 (kle 1),我们就可以很轻松地算出长方形的长和宽。

    同时,我们只需要枚举 (a)(b) 就可以求出所有的三角形。

    这就是满分做法的核心部件。

    Code

    虽然挺烦的,但是锻炼一下码力也是不错的。

    #include <cstdio>
    #include <cctype>
    using namespace std;
    
    typedef long long ll;
    const int mod = 1e9 + 7;
    
    inline bool is_int(double b) { return (b - int(b)) < 1e-5; }
    
    inline int read()
    {
    	int ch = getchar(), t = 1, n = 0;
    	while (isspace(ch)) { ch = getchar(); }
    	if (ch == '-') { t = -1, ch = getchar(); }
    	while (isdigit(ch)) { n = n * 10 + ch - '0', ch = getchar(); }
    	return n * t;
    }
    
    int main()
    {
    	ll ans = 0;
    	int n, m, s;
    	double k;
    
    	scanf("%d%d%d", &n, &m, &s);
    
    	for (int i = 1; i * i <= s; i++)
    	{
    		if (!(s % i))
    		{
    			if (i <= n && (s / i) <= m)
    				ans = (ans + (ll(n - i + 1) * ll(m - s / i + 1) % mod * 4)) % mod;
    			if (i * i != s && i <= m && (s / i) <= n)
    				ans = (ans + (ll(n - s / i + 1) * ll(m - i + 1) % mod * 4)) % mod;
    		}
    
    		for (int j = i; i * i + j * j <= s; j++)
    		{
    			k = double(s) / (i * i + j * j);
    
    			if (is_int(k * i) && is_int(k * j))
    			{
    				if (j + k * i <= n && k * j <= m)
    					ans = (ans + (ll(n - j - k * i + 1) * ll(m - k * j + 1)) % mod * (4 - 2 * (i == j))) % mod;
    				if (k * j <= n && j + k * i <= m)
    					ans = (ans + (ll(m - j - k * i + 1) * ll(n - k * j + 1)) % mod * (4 - 2 * (i == j))) % mod;
    			}
    		}
    	}
    	
    	printf("%lld
    ", ans);
    
    
    	return 0;
    }
    

    后记

    一道有意思的模拟题,虽然掺杂了一点数学知识。

    做题时,这种题一般很无聊,但做上几题其实也没有什么坏处。

  • 相关阅读:
    markdown文件的基本常用编写
    寒假作业安排及注意点
    Day2
    Day1
    Python格式化
    Python 遍历字典的键值
    python 判断是否为空
    git 回退版本
    Python获取当前文件夹位置
    Python3, Python2 获取当前时间
  • 原文地址:https://www.cnblogs.com/5ab-juruo/p/solution-20200530-wordless.html
Copyright © 2020-2023  润新知