[Nowcoder]2020牛客寒假算法基础集训营题集

一、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 }

持续更新中。。。

猜你喜欢

转载自www.cnblogs.com/jinkun113/p/12285921.html
今日推荐