牛客寒假算法训练营2
C.算概率
链接:https://ac.nowcoder.com/acm/contest/3003/C
来源:牛客网
牛牛刚刚考完了期末,尽管 牛牛 做答了所有 n 道题目,但他不知道有多少题是正确的。
不过,牛牛 知道第 i道题的正确率是 pi。
牛牛 想知道这 n 题里恰好有 0,1,…,n 题正确的概率分别是多少,对 10^9+7 取模。对 10^9 + 7取模的含义是:对于一个 b≠0 的不可约分数 a/b,存在 q 使得 b×q mod (109+7)=a,q 即为 a/b 对 10^9+7取模的结果。
这里其实就是逆元,在考虑的时候,被分数的模数有点吓到了,不知道从何下手,以及如何转换,其实直接用就可以了。。。。也算是涨了一波见识,顺便温习了一下逆元的知识。
由费马小定理我们知道,a mod p如果P为质数,而且a不为p的倍数,那么有 a^(p-1) = 1(mod p),所以a^(p - 2) = 1 / a(mod p),即a的逆元,用于除法的模运算
这道题,给出的概率就直接用就行,不用去考虑什么转化,只要注意取模就好
#include <cstdio>
#include <algorithm>
using namespace std;
#define ll long long
const int base = 1e9 + 7;
ll p[2003];
ll ans[2003][2003];
int n;
void input(){
scanf("%d",&n);
for(int i = 1;i <= n;i++){
scanf("%lld",&p[i]);
}
}
void work(){
ans[0][0] = 1;
for(int i = 1;i <= n;i++){
ans[i][0] = ans[i - 1][0] * (base + 1 - p[i]) % base;
}
for(int i = 1;i <= n;i++){
for(int j = 1; j <= i;j++){
ans[i][j] = (ans[i - 1][j] * (base + 1 - p[i]) + ans[i - 1][j - 1] * p[i]) % base;
}
}
for(int i = 0;i <= n;i++){
printf("%lld ",ans[n][i]);
}
}
int main(){
input();
work();
return 0;
}
D-数三角
链接:https://ac.nowcoder.com/acm/contest/3003/D
来源:牛客网
牛牛得到了一个平面,这个平面上有 n 个不重合的点,第 i 个点的坐标为 (xi,yi)。
牛牛想知道,这 n 个点形成的三角形中,总共有多少个钝角三角形
高中的知识又全部倒给老师了。。。怎么判断钝角都给忘了。。。。,题目本身感觉也不是特别难的样子,自己做的时候又是判断长度,判断距离的,给搞得太复杂了。。。
#include <cstdio>
#include <utility>
#include <vector>
#include <math.h>
using namespace std;
const int maxn = 503;
int x[maxn];
int y[maxn];
int n;
void input(){
scanf("%d",&n);
int a,b;
for(int i = 0;i < n;i++){
scanf("%d%d",&x[i],&y[i]);
}
}
bool check(int a,int b,int c){
if((x[a] - x[b]) * (x[c] - x[b]) + (y[a] - y[b]) * (y[c] - y[b]) < 0){
if((x[a] - x[b]) * (y[c] - y[b]) - (x[c] - x[b]) * (y[a] - y[b]) != 0){
return true;
}
}
return false;
}
void work(){
int ans = 0;
for(int i = 0;i < n - 2;i++){
for(int j = i + 1;j < n - 1;j++){
for(int k = j + 1;k < n;k++){
if(check(i,j,k) || check(k,i,j) || check(j,k,i)){
ans++;
}
}
}
}
printf("%d\n",ans);
}
int main(){
input();
work();
return 0;
}
F-拿物品
链接:https://ac.nowcoder.com/acm/contest/3003/F
来源:牛客网
牛牛和 牛可乐 面前有 n 个物品,这些物品编号为 1,2,…,n每个物品有两个属性 ai,bi。
牛牛与 牛可乐会轮流从剩下物品中任意拿走一个, 牛牛先选取。
设 牛牛选取的物品编号集合为 H,牛可乐选取的物品编号的集合为 T,取完之后,牛牛 得分为 ∑i∈H;而 牛可乐得分为 ∑i∈Tbii。
牛牛和 牛可乐都希望自己的得分尽量比对方大(即最大化自己与对方得分的差)。
你需要求出两人都使用最优策略的情况下,最终分别会选择哪些物品,若有多种答案或输出顺序,输出任意一种。
每一个物品对于自己的而言的战略价值就等于 a + b,所以双方每一次选取战略价值最高的对自己最有利。其实就是贪心啦。。。
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
#define ll long long
const int maxn = 2e5 + 7;
int n;
struct node{
ll a;
int num;
};
node res[maxn];
bool cmp(node a,node b){
return a.a > b.a;
}
void input(){
scanf("%d",&n);
for(int i = 0;i < n