牛客练习赛 26

比赛链接:传送门
链接:https://www.nowcoder.com/acm/contest/180/A
A

题目描述
小a的平面上有n个X型不明物体,但是他不确定他们的位置。现在请你来确定他们的位置,使得划分形成的平面尽量多
输入描述:
一个整数n,如题所示
输出描述:
一个整数,表示最多把平面分成多少份
示例1
输入

2
输出

11

平面分割问题,直线划分平面,有个公式就是
Cn 0+Cn 1+Cn 2
推导大致是这样的:详见传送门
当有n-1条直线时,平面最多被分成了f(n-1)个区域。则第n条直线要是切成的区域数最多,就必须与每条直线相交且不能有同一交点。这样就会得到n-1个交点。这些交点将第n条直线分为2条射线和n-2条线断。而每条射线和线断将以有的区域一分为二。这样就多出了2+(n-2)个区域。
f(n)=f(n-1)+n
=f(n-2)+(n-1)+n
=……
=f(1)+1+2+……+n
=n(n+1)/2+1

#include<stdio.h>
int main()
{ 
   long long n,L1;
   scanf("%lld",&n);
    n=n*2;
       L1=(n*n+n+2)/2;      //直线划分平面 

       printf("%lld\n",L1);

   return 0;
}

链接:https://www.nowcoder.com/acm/contest/180/B

B
题目描述
小a有个烟花,每个烟花代表着互不相同的颜色,对于第个烟花,它有的概率点燃,现在小a要去点燃它们,他想知道产生颜色的期望个数 及 产生恰好产生种颜色的概率

输入描述:
第一行两个整数
接下来一行个数,第个数表示第个烟花被点燃的概率
输出描述:
输出有两行
第一行表示产生不同颜色的期望个数
第二行表示产生恰好种颜色的概率
以换行符分割

每种颜色的个数是1,因为期望的线性性质
,所以积分 ans就等于xi*pi的积分了,等于概率之和
第二问,dp[i][j]表示当前有i个烟花恰好有j个烟花被点燃。

#include<cstdio>
#include<algorithm>
using namespace std;
double p[1000005],dp[100005][105];
int main(){
    int n,k;
    scanf("%d%d",&n,&k);
    double ans=0;
    for (int i=1; i<=n; i++){
        scanf("%lf",&p[i]);
        ans+=p[i];
    }
    printf("%0.4lf\n",ans);
    dp[0][0]=1;
    for (int i=1; i<=n; i++){

        for (int j=0; j<=min(i,k); j++){
            dp[i][j+1]+=dp[i-1][j]*p[i];

            dp[i][j]+=dp[i-1][j]*((double)1-p[i]);

        }
    } 
    printf("%0.4lf\n",dp[n][k]);

}

如果题目卡空间的话,就需要用到滚动数组优化,放标程了

#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN = 100001;
int N, K;
double p[MAXN], f[2][MAXN];
int main() {
    scanf("%d %d", &N, &K);
    double sum = 0;
    for(int i = 1; i <= N; i++) scanf("%lf", &p[i]), sum += p[i];
    printf("%.4lf\n", sum);
    int o = 0;
    f[o][1] = p[1]; f[o][0] = 1 - p[1];
    for(int i = 2; i <= N; i++) {
        o ^= 1;
        for(int j = 0; j <= min(i, K); j++)
            f[o][j] = f[o ^ 1][j - 1] * p[i] + f[o ^ 1][j] * (1 - p[i]);
    }
    printf("%.4lf", f[o][K]);
    return 0;
}

链接:https://www.nowcoder.com/acm/contest/180/C
C

题目描述
小a的国家里有n个城市,其中第i和第i - 1个城市之间有无向道路连接,特殊的,第1个城市仅与第2个城市相连
为了减轻道路维护负担,城市规划局局长MXT给出了m个要求,他想让小a断开一些道路,使得任意1 ≤ i ≤ m ,城市xi不能到达城市yi
同时最小化断开道路的数量。

输入描述:
第一行两个整数n, m,分别表示城市的数量和请求的数量
接下来m行,每行两个整数x,y,表示需要使得x不能到达y
输出描述:
输出一个整数,表示最小断开桥的数量
示例1
输入

4 2
1 3
2 4
输出

1
说明
可以断开(2, 3)城市之间的道路

不知道为啥比赛的时候就是看不出来,难道是心太急了,我竟然想到了最小割,看这时间复杂度怎么可能,
然后竟然是贪心的做法
直接上题解了,开学了,人也变得懒起来了
考虑一个很显然的 O(mlog(m))的做法 首先对所有线段按照右端点排序,然后每次在右端点处切 但是m达到了 10^7级别,所以不能通过此题

由于题目保证所有线段的值域为1-n ,我们可以对所有左端点,直接记录出右端点最靠左的 位置 同样每次切右端点,扫一遍即可 时间复杂度: O(m)

#include<cstdio>
const int MAXN = 1e6 + 10;
#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1<<22, stdin), p1 == p2) ? EOF : *p1++)
#define min(a, b) (a < b ? a : b)
char buf[(1 << 22)], *p1 = buf, *p2 = buf;
inline int read() {
    char c = getchar(); int x = 0, f = 1;
    while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
    while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    return x * f;
}
int N, M;
int r[MAXN];
int main() {
    N = read(); M = read();
    for(int i = 1; i <= N; i++) r[i] = N + 1;
    for(int i = 1; i <= M; i++) {
        int x = read(), y = read();
        r[x] = min(y, r[x]);
    }
    int cur = N + 1, ans = 0;
    for(int i = 1; i <= N; i++) {
        cur = min(cur, r[i]);
        if(i == cur) cur = r[i], ans++;
    }
    printf("%d", ans);
    return 0;
}

链接:https://www.nowcoder.com/acm/contest/180/D
D

题目描述
小a有n个数,他提出了一个很有意思的问题:他想知道对于任意的x, y,能否将x与这n个数中的任意多个数异或任意多次后变为y

输入描述:
第一行为一个整数n,表示元素个数
第二行一行包含n个整数,分别代表序列中的元素
第三行为一个整数Q,表示询问次数
接下来Q行,每行两个数x,y,含义如题所示
输出描述:
输出Q行,若x可以变换为y,输出“YES”,否则输出“NO”
示例1
输入

5
1 2 3 4 5
3
6 7
2 1
3 8
输出

YES
YES
NO

该题首先会发现异或有一个性质就是 x^y=z,然后 x^z=y;
然后该题就只要找出这个集合能不能异或出y就ok了
那么就是线性基经典操作了 额,以前听别人说起过,但是一直没学,伤心
上个标程记录一下

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN = 32, B = 31;
inline int read() {
    char c = getchar(); int x = 0, f = 1;
    while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
    while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    return x * f;
}
int N;
int P[MAXN];
void Insert(int x) {
    for(int i = B; i >= 0; i--) {
        if((x >> i) & 1) {
            if(!P[i]) {P[i] = x; break;}
            x ^= P[i];
        }
    }
}

int Query(int x) {
    for(int i = B; i >= 0; i--) {
        if((x >> i) & 1) {
            if(!P[i]) return 0;
            x ^= P[i];
        }
    }
    if(x == 0) return 1;
    else return 0;
}

int main(){ 
    N = read();
    for(int i = 1; i <= N; i++) {
        int val = read(); Insert(val);
    }
    int Q = read();
    while(Q--) {
        int x = read(), y = read();
        if(Query(x ^ y)) puts("YES");
        else puts("NO");
    }
}

其他的题目日后再记录呜呜呜

猜你喜欢

转载自blog.csdn.net/qq_37774171/article/details/82533552