20200206 第二场
进度(7 / 10) 未完成:H / I / J
A、做游戏
1、链接
https://ac.nowcoder.com/acm/contest/3003/A
2、题面
牛牛和 牛可乐在玩石头剪刀布。
3、思路
小型贪心。牛牛出石头时牛可乐优先出剪刀,同理剪刀-布,布-石头。三次比较均取两者较小值,剩下的便是不可能获胜的局了。
4、代码
1 #include2 using namespace std; 3 4 long long a, b, c, d, e, f; 5 6 int main() { 7 cin >> a >> b >> c >> d >> e >> f; 8 cout << min(a, e) + min(b, f) + min(c, d); 9 return 0; 10 }
B、排数字
1、链接
https://ac.nowcoder.com/acm/contest/3003/B
2、题面
牛可乐 最喜爱的字符串是 616。
3、思路
签到题。将字符串中1和6提取出来,以616161...的形式排列为最优解,则统计1和6的个数并处理一下即可得到答案。
4、代码
1 #include2 using namespace std; 3 4 #define MAXN 200005 5 6 int n, a, b; 7 char s[MAXN]; 8 9 int main() { 10 cin >> n >> s; 11 for (int i = 0; i < n; i++) a += s[i] == '1', b += s[i] == '6'; 12 cout << min(a, b - 1); 13 return 0; 14 }
C、算概率
1、链接
https://ac.nowcoder.com/acm/contest/3003/C
2、题面
牛牛刚刚考完了期末,尽管 牛牛 做答了所有 n 道题目,但他不知道有多少题是正确的。
不过,牛牛 知道第 ii 道题的正确率是 pipi。
牛牛 想知道这 n 题里恰好有 0,1,…,n0,1,…,n 题正确的概率分别是多少,对 109+710^9+7 取模。
对 109+710^9+7 取模的含义是:对于一个 b≠0b !=0 的不可约分数 aba/b,存在 qq 使得 b×q mod (109+7)=ab * q mod (10^9+7) =a,qq 即为 aba / b 对 109+710^9+7 取模的结果。
3、思路
自己瞎捣鼓了许久没做出来。看了下题解,发现我duck不必纠结于将pi化成分数形式。
这也算是一道DP题。设f[i][j]表示前i道题里j道题正确的概率,状态转移:f[i][j] = f[i - 1][j - 1] * p[i] + f[i - 1][j] * p_[i],其中p_[i]表示做错的概率。
根据题意,p_[i] = mod + 1 - p[i],上述数据全部需要取模。
4、代码
1 #include2 using namespace std; 3 4 typedef long long ll; 5 6 #define MAXN 2005 7 #define MOD 1000000007 8 9 ll n, a[MAXN], b[MAXN], f[MAXN][MAXN]; 10 11 int main() { 12 cin >> n; 13 for (int i = 1; i <= n; i++) 14 cin >> a[i], b[i] = (MOD + 1 - a[i]) % MOD; 15 f[0][0] = 1; 16 for (int i = 1; i <= n; i++) { 17 f[i][0] = (f[i - 1][0] * b[i]) % MOD; 18 for (int j = 1; j <= i; j++) 19 f[i][j] = ((f[i - 1][j] * b[i]) % MOD + (f[i - 1][j - 1] * a[i]) % MOD) % MOD; 20 } 21 for (int i = 0; i <= n; i++) cout << f[n][i] << ' '; 22 return 0; 23 }
D、数三角
1、链接
https://ac.nowcoder.com/acm/contest/3003/D
2、题面
牛牛得到了一个平面,这个平面上有 n 个不重合的点,第 i 个点的坐标为 (xi,yi)。
3、思路
平面几何题。枚举任意两个点,再选择第三个点,看是否满足钝角三角形的条件。设当前选择的两个点为A, B,如图所示,
根据几何知识,当且仅当第三个点位于如下两种位置,可以与A, B组成钝角三角形:
①以AB中点为圆心的圆内;
②不在与AB所连的线段垂直且分别过A, B的两条直线之间(排除①的圆内)。
文字描述显得比较拗口,但图示就比较清晰了。那么:
对于①,求得中点和半径,判定第三个点和圆心距离是否小于半径即可;
对于②,求得直线AB的斜率,进而求得与之垂直的直线的斜率k,分别将A, B, 所求的第三个点代入求得所在直线的截距b,如果第三个点的b小于A的或者大于B的,即满足条件。
平面几何题一个常见的要考虑的问题就是斜率为0或者斜率为无穷大的情况,需要特殊考虑。
4、代码
1 #include2 using namespace std; 3 4 #define MAXN 200005 5 6 int n, ans; 7 double x[MAXN], y[MAXN]; 8 9 double dis(int a, int b) { 10 return sqrt((y[a] - y[b]) * (y[a] - y[b]) + (x[a] - x[b]) * (x[a] - x[b])); 11 } 12 13 int main() { 14 cin >> n; 15 for (int i = 1; i <= n; i++) cin >> x[i] >> y[i]; 16 for (int i = 1; i <= n - 2; i++) 17 for (int j = i + 1; j <= n - 1; j++) { 18 x[0] = (x[j] + x[i]) / 2.0, y[0] = (y[j] + y[i]) / 2.0; 19 double r = dis(i, 0); 20 for (int l = j + 1; l <= n; l++) { 21 if (y[j] == y[i]) 22 ans += (x[l] < min(x[i], x[j]) || x[l] > max(x[i], x[j])) && y[l] != y[i]; 23 else if (x[j] == x[i]) 24 ans += (y[l] < min(y[i], y[j]) || y[l] > max(y[i], y[j])) && x[l] != x[i]; 25 else { 26 double k = -1 / ((y[j] - y[i]) / (x[j] - x[i])); 27 double bi = y[i] - k * x[i], bj = y[j] - k * x[j]; 28 if (-1 / ((y[l] - y[i]) / (x[l] - x[i])) == k) continue; 29 double bl = y[l] - k * x[l]; 30 ans += bl < min(bi, bj) || max(bi, bj) < bl; 31 } 32 ans += dis(l, 0) < r; 33 } 34 } 35 cout << ans; 36 return 0; 37 }
E、做计数
1、链接
https://ac.nowcoder.com/acm/contest/3003/E
2、题面
这一天,牛牛与 牛魔王相遇了――然而这并不在 牛牛期望之中。
牛魔王不出意料又给 牛牛一道看似很难的题目:求有多少个不同的正整数三元组 (i,j,k) 满足
3、思路
看到根号第一反应是平方。数学符号太难打了,直接复制别人的题解好了。
然后我就一个个i去枚举,,果不其然就T了。想了许久也没找到个好办法,看了题解给的code:
枚举小于n的完全平方数x,再枚举x的因子,仅需在sqrt(x)范围内枚举,由于(i, j)和(j, i)不等价,再在结果上*2即可,当然(i, i)需要特殊考虑。
4、代码
1 #include2 using namespace std; 3 4 int n, ans; 5 6 int main() { 7 cin >> n; 8 for (int i = 1; i <= sqrt(n); i++) { 9 int o = i * i; 10 for (int j = 1; j <= sqrt(o); j++) 11 ans += i == j ? 1 : o % j == 0 ? 2 : 0; 12 } 13 cout << ans; 14 return 0; 15 }
F、拿物品
1、链接
https://ac.nowcoder.com/acm/contest/3003/F
2、题面
牛牛和 牛可乐 面前有 n 个物品,这些物品编号为 1,2,…,nn ,每个物品有两个属性 ai,bi 。
3、思路
贪心。这题思路不错,值得细品的一种贪心。
由于目的是使得分差最大,对于物品i,A得ai,B得bi,如果A拿了,相当于A得了分,而B同时没得到分,则相当于分差拉开了ai +bi。
根据这个贪心思路,我们将物品按照ai + bi从大到小的顺序排序,然后两人依次拿即可。
4、代码
1 #include2 using namespace std; 3 4 #define MAXN 200005 5 6 int n, ans[2][MAXN], o = 1; 7 8 struct item { 9 int p[3], o; 10 } a[MAXN]; 11 12 struct cmp { 13 bool operator () (item a, item b) { 14 return a.p[2] > b.p[2]; 15 } 16 } x; 17 18 int main() { 19 cin >> n; 20 for (int j = 0; j <= 1; j++) 21 for (int i = 1; i <= n; i++) cin >> a[i].p[j], a[i].o = i; 22 for (int i = 1; i <= n; i++) a[i].p[2] = a[i].p[0] + a[i].p[1]; 23 sort(a + 1, a + n + 1, x); 24 for (int i = 1; i <= n; i++) o ^= 1, ans[o][(i - 1) / 2 + 1] = a[i].o; 25 for (int i = 1; i <= n - n / 2; i++) cout << ans[0][i] << ' '; 26 cout << endl; 27 for (int i = 1; i <= n / 2; i++) cout << ans[1][i] << ' '; 28 return 0; 29 }
G、判正误
1、链接
https://ac.nowcoder.com/acm/contest/3003/G
2、题面
牛可乐有七个整数 a,b,c,d,e,f,g 并且他猜想 a^d+b^e+c^f=g。但牛可乐无法进行如此庞大的计算。
请验证牛可乐的猜想是否成立。
3、思路
这么憨批的签到题我还去推式子。。想着应该没这么简单。
然后写个快速幂又被卡常@!%@#¥#
可以直接用pow,可以写快速幂,快速幂模数设成1e9+7可过,列一下常用模数方便以后用:
12255871, 16341163, 21788233, 29050993, 38734667, 51646229, 68861641, 91815541, 1000000007, 1000000009
4、代码
1 #include2 using namespace std; 3 4 typedef long long ll; 5 #define MOD 1000000007 6 7 ll t, a, b, c, d, e, f, g; 8 9 ll qpow(ll x, ll y) { 10 ll o = x, res = 1; 11 while (y) { 12 if (y & 1) (res *= o) %= MOD; 13 (o *= o) %= MOD, y >>= 1; 14 } 15 return res; 16 } 17 18 int main() { 19 cin >> t; 20 for (int i = 1; i <= t; i++) { 21 cin >> a >> b >> c >> d >> e >> f >> g; 22 printf(qpow(a, d) + qpow(b, e) + qpow(c, f) == g ? "Yes\n" : "No\n"); 23 } 24 return 0; 25 }