一、20200208 第一场
A、honoka和格点三角形
1、链接
https://ac.nowcoder.com/acm/contest/3002/A
2、题面
honoka最近在研究三角形计数问题。
她认为,满足以下三个条件的三角形是“好三角形”。
1.三角形的三个顶点均为格点,即横坐标和纵坐标均为整数。
2.三角形的面积为 。
3.三角形至少有一条边和 轴或 轴平行。
honoka想知道,在平面中选取一个大小为 的矩形格点阵,可以找到多少个不同的“好三角形”?由于答案可能过大,请对 取模。
3、思路
根据题目限制条件,这样的三角形可以分类为:底边水平,底边垂直;每一类底边可以为1也可以为2,所以总共为4类。
以底边垂直且长度为1为例,如图所示,对于n * m的矩形格点阵,存在(n - 1) * m个这样的底边;对于每一个这样的底边,可以找出n个向右延伸的三角形。排除最靠右的两列,总共n * (m - 2) * (n - 1),同理加上向左延伸的三角形,共有2 * (n - 1) * (m - 2) * n个此类型三角形。
同理,底边垂直长度为2的三角形有2 * (n - 2) * (m - 1) * n个;
底边水平长度为1的三角形也有2 * (m - 1) * (n - 2) * m个,但是由于其中的直角三角形在之前已经被计算过了,所以要稍微修改一下:(m - 1) * (n - 2) * (2 * m - 4)。
同理,底边水平长度为2的三角形有(m - 2) * (n - 1) * (2 * m - 4)个。
答案就是把上述四种三角形加起来。
到现在这道题就做完了,但由于n, m <= 10 ^ 9,计算时超出long long范围,直接相加会溢出(我懒得加了然后就WA了),所以要化成一个合适的形式,因式分解一下就行了。
4、代码
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define MOD 1000000007 5 typedef long long ll; 6 7 ll n, m; 8 9 int main() { 10 cin >> n >> m; 11 cout << ((2 * m + 2 * n - 4) % MOD) * ((2 * n * m - 3 * n - 3 * m + 4) % MOD) % MOD; 12 return 0; 13 }
B、kotori和bangdream
1、链接
https://ac.nowcoder.com/acm/contest/3002/B
2、题面
有一天,kotori发现了一个和lovelive相似的游戏:bangdream。令她惊讶的是,这个游戏和lovelive居然是同一个公司出的!
kotori经过一段时间的练习后已经变得非常触,每个音符 x% 的概率perfect,获得 分, (100−x)% 概率great,获得 分。
已知一首歌有 个音符。kotori想知道,不考虑连击加成的话,一首歌得分的期望是多少?
3、思路
签到题。思路略。这里学到了一个cout保留小数的方法: cout << fixed << setprecision(x) << ...,x表示保留小数位数。
4、代码
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 double n, x, a, b; 5 6 int main() { 7 cin >> n >> x >> a >> b; 8 cout << fixed << setprecision(2) << n * (x / 100 * a + (1 - x / 100) * b); 9 return 0; 10 }
C、
1、链接
https://ac.nowcoder.com/acm/contest/3002/C
2、题面
3、思路
4、代码
D、hanayo和米饭
1、链接
https://ac.nowcoder.com/acm/contest/3002/D
2、题面
hanayo很喜欢吃米饭。
有一天,她拿出了 个碗,第一个碗装了 粒米饭,第二个碗装了 粒米饭,以此类推,第 个碗装了 粒米饭。
然而,爱搞恶作剧的rin把所有的碗的顺序打乱,并拿走了一个碗。hanayo想知道,rin拿走的碗里有多少粒米饭?
3、思路
签到题,略。
4、代码
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long ll; 5 6 ll n, o, tot; 7 8 int main() { 9 cin >> n; 10 for (int i = 1; i <= n - 1; i++) cin >> o, tot += o; 11 cout << (1 + n) * n / 2 - tot; 12 return 0; 13 }
E、rin和快速迭代
1、链接
https://ac.nowcoder.com/acm/contest/3002/E
2、题面
rin最近喜欢上了数论。
然而数论实在太复杂了,她只能研究一些简单的问题。
这天,她在研究正整数因子个数的时候,想到了一个“快速迭代”算法。设 为 的因子个数,将 迭代下去,rin猜想任意正整数最终都会变成 。
例如: 。
她希望你帮她验证一下。她会给你一个正整数 ,让你输出它在迭代过程中,第一次迭代成 的迭代次数。
3、思路
(本来这也是个签到题吧。。结果我弄了大半天,烦)
虽然数据看着很大,n <= 10 ^ 12,但众所周知求n的约数,只需枚举1到sqrt(n),又根据题意的迭代方式,实际复杂度仅仅只有O(sqrt(n)) = O(10 ^ 6)。然而我首先没注意到如果它是完全平方数的情况,直接枚举完*2,然后就巴拉巴拉弄了好久,人傻了。最近码力明显下滑了。
不过这题又非暴力解法,由“约数个数定理”得:
这样就有了另一种思路,按下不表。
4、代码
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long ll; 5 6 ll n; 7 8 ll work(ll o, ll d) { 9 if (o == 2) return d; 10 ll x = 0; 11 for (ll i = 1; i <= sqrt(o); i++) x += o % i ? 0 : i * i == o ? 1 : 2; 12 return work(x, d + 1); 13 } 14 15 int main() { 16 cin >> n; 17 cout << work(n, 0); 18 return 0; 19 }
持续更新中。。。