zoukankan      html  css  js  c++  java
  • 2019nc#2

    A Eddy Walker

    题意

    你有n个点(0~n-1),按顺序形成一个环,初始时你在0的位子,你随机顺时针走一步或者逆时针走一步,

    一旦你走到一个点后,环上所有点都被经过至少一次后,你就必须停下来。

    问你最后停留在m这个位子的概率是多少。

     注意输出的答案是前缀积。

    思路

    有意思的概率题。

    读懂题意后发现这道题不难,模拟下可以发现在最后落在(1~n-1)的位子是等概率的,落在0这个位子是不可能的(除非n==1)。

    #include <iostream>
    #include <vector>
    #include <queue>
    #include <algorithm>
    using namespace std;
    #define pb push_back
    #define fi first
    #define se second
    #define debug(x) cerr<<#x << " := " << x << endl;
    #define bug cerr<<"-----------------------"<<endl;
    #define FOR(a, b, c) for(int a = b; a <= c; ++ a)
    
    typedef long long ll;
    typedef long double ld;
    typedef pair<int, int> pii;
    typedef pair<ll, ll> pll;
    
    
    template<class T> void _R(T &x) { cin >> x; }
    void _R(int &x) { scanf("%d", &x); }
    void _R(ll &x) { scanf("%lld", &x); }
    void _R(double &x) { scanf("%lf", &x); }
    void _R(char &x) { scanf(" %c", &x); }
    void _R(char *x) { scanf("%s", x); }
    void R() {}
    template<class T, class... U> void R(T &head, U &... tail) { _R(head); R(tail...); }
    
    
    template<typename T>
    inline T read(T&x){
        x=0;int f=0;char ch=getchar();
        while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
        while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
        return x=f?-x:x;
    }
    
    const int inf = 0x3f3f3f3f;
    
    const int mod = 1e9+7;
    
    /**********showtime************/
                ll ksm(ll a, ll b) {
                    ll res = 1;
                    while(b > 0) {
                        if(b & 1) res = res * a % mod;
                        a = a * a % mod;
                        b = b >> 1;
                    }
                    return res;
                }
    int main(){
                int T;  scanf("%d", &T);
                ll res = 1;
                while(T--){
                    ll n,m;
                    scanf("%lld%lld", &n, &m);
                    if(n == 1 && m == 0) res = res;
                    else {
                        if(m == 0) res = res * 0;
                        else {
                            res = res * ksm(n-1, mod-2) % mod;
                        }
                    }
                    printf("%lld
    ", res);
                }
    
                return 0;
    }
    View Code

     B Eddy Walker 2

     BM

    D Kth Minimum Clique

     题意:

     在一个无向图中,找出一个权值为第K小的最小团,最小团的定义为选出的公共节点间有边直接联通。

     思路:

     感觉实现起来不太难。既然要选择第K小的,我们可以从小到大做。每次通过最小的一个最小团扩展,可以利用bitset优化判断扩展的可行性。

     即利用优先队列,从其中取出的第k个就是答案。

     有点像dji找最短路

    #include<bits/stdc++.h>
    using namespace std;
    #define pb push_back
    #define fi first
    #define se second
    #define debug(x) cerr<<#x << " := " << x << endl;
    #define bug cerr<<"-----------------------"<<endl;
    #define FOR(a, b, c) for(int a = b; a <= c; ++ a)
     
    typedef long long ll;
    typedef long double ld;
    typedef pair<int, int> pii;
    typedef pair<ll, ll> pll;
     
     
    template<class T> void _R(T &x) { cin >> x; }
    void _R(int &x) { scanf("%d", &x); }
    void _R(ll &x) { scanf("%lld", &x); }
    void _R(double &x) { scanf("%lf", &x); }
    void _R(char &x) { scanf(" %c", &x); }
    void _R(char *x) { scanf("%s", x); }
    void R() {}
    template<class T, class... U> void R(T &head, U &... tail) { _R(head); R(tail...); }
     
     
    template<typename T>
    inline T read(T&x){
        x=0;int f=0;char ch=getchar();
        while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
        while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
        return x=f?-x:x;
    }
     
    const int inf = 0x3f3f3f3f;
     
    const int mod = 1e9+7;
     
    /**********showtime************/
     
                const int maxn = 109;
                char str[maxn];
                struct node{
                    ll val;
                    bitset<109>bs;
                    bool operator<(const node & o) const{
                        return val > o.val;
                    }
                }a[maxn];
    int main(){
                int n,k;
                scanf("%d%d", &n, &k);
                for(int i=1; i<=n; i++) {
                    scanf("%lld", &a[i].val);
                }
                for(int i=1; i<=n; i++) {
                    scanf("%s", str+1);
                    for(int j=1; j<=n; j++) {
                        if(str[j] == '1')a[i].bs.set(j);
                    }
                } 
     
                priority_queue<node>que;
                node s;
                s.val = 0;
                s.bs.reset();
                que.push(s);
                int flag = 0;ll res;
                while(!que.empty()) {
                    node u = que.top();
                    que.pop();
                    k -- ;
                    if(k == 0) {
                        flag = 1;
                        res = u.val;
                        break;
                    }
                    int mx = 1;
                    for(int i=1; i<=n; i++) {
                        if(u.bs[i] == 1) mx = i + 1;
                    }
     
                    for(int i=mx; i<=n; i++) {
                        if((u.bs & a[i].bs) == u.bs) {
                            u.bs.set(i);    u.val += a[i].val;
                            que.push(u);
                            u.bs.reset(i);    u.val -= a[i].val;
                        }
                    }
                }
                if(flag) printf("%lld
    ", res);
                else puts("-1");
                return 0;
    }
    View Code

    E MAZE

    线段树,dp

    F Partition problem

    比赛时过的,双向搜索降低复杂度(队友搞的,我还没搞)

    I Inside A Rectangle

    dp

    H Second Large Rectangle

    比赛时过的。DP出面积,找出次大的

    (队友搞的,我还没搞)

    J Subarray

    题意:

    有一个长度为1E9,值为{-1,1}的数组,保证只有n(<1e6)个区间等于1,且1的个数小于1e7。

    求有多少对区间的区间和大于0。

    思路:

    首先把被答案区间所包含的点都找出来。最多只有3e7个点。怎么找?

    从小到达遍历数组,把每个区间向右扩展的长度找出来,

    从大到小遍历数组,把每个区间向左扩展的长度找出来。

    然后计算每个点的前缀和。在一个点前面且前缀和小于当前点的前缀和的一个点对应ans++。

    由于前缀和的变化大小为1,所以不用树状数组即可完成。

    #include <bits/stdc++.h>
    using namespace std;
    #define pb push_back
    #define fi first
    #define se second
    #define debug(x) cerr<<#x << " := " << x << endl;
    #define bug cerr<<"-----------------------"<<endl;
    #define FOR(a, b, c) for(int a = b; a <= c; ++ a)
    
    typedef long long ll;
    typedef long double ld;
    typedef pair<int, int> pii;
    typedef pair<ll, ll> pll;
    
    
    template<class T> void _R(T &x) { cin >> x; }
    void _R(int &x) { scanf("%d", &x); }
    void _R(ll &x) { scanf("%lld", &x); }
    void _R(double &x) { scanf("%lf", &x); }
    void _R(char &x) { scanf(" %c", &x); }
    void _R(char *x) { scanf("%s", x); }
    void R() {}
    template<class T, class... U> void R(T &head, U &... tail) { _R(head); R(tail...); }
    
    
    template<typename T>
    inline T read(T&x){
        x=0;int f=0;char ch=getchar();
        while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
        while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
        return x=f?-x:x;
    }
    
    const int inf = 0x3f3f3f3f;
    const ll inff = 0x3f3f3f3f3f3f3f3f;
    const int mod = 1e9+7;
    
    /**********showtime************/
                const int maxm = 2e7+9;
                const int maxn = 1e6+9;
                int le[maxn],ri[maxn];
                int lto[maxn],rto[maxn];
                ll f[maxm];
                int g(int x) {
                    return x + 10000000;
                }
    int main(){
                int n;
                scanf("%d", &n);
    
                for(int i=1; i<=n; i++) scanf("%d%d", &le[i], &ri[i]);
    
                int sum = 0;
                /// 向右扩展
                le[n+1] = 1000000000;
                for(int i=1; i<=n; i++) {
                    sum += ri[i] - le[i] + 1;
                    rto[i] = min(sum, le[i+1] - ri[i] - 1);
                    sum -= le[i+1] - ri[i] - 1;
                    if(sum < 0) sum = 0;
                }
                /// 向左扩展
                sum = 0;
                ri[0] = -1;
    
                for(int i=n; i>=1; i--) {
                    sum += ri[i] - le[i] + 1;
                    lto[i] = min(sum , le[i] - ri[i-1] -1);
                    sum -= le[i] - ri[i-1] - 1;
                    if(sum < 0) sum = 0;
                }
    
                ///计算每个点的前缀和。lowsum保存前缀和比当前点小的个数
                ll  ans = 0, lowsum = 0;
                int s = 0, pos = 0;
                f[g(0)] = 1;
                for(int i=1; i<=n; i++) {
    
                    for(int j=max(pos, le[i] - lto[i]); j<=ri[i] + rto[i]; j++) {
    
                        if(j>=le[i] && j <= ri[i]) {
                            lowsum += f[g(s)];
                            s++;
                            f[g(s)]++;
                            ans += lowsum;
                        }
                        else {
                            s--;
                            lowsum -= f[g(s)];
                            f[g(s)]++;
                            ans += lowsum;
                        }
    //                    cout<<j<<" "<<lowsum<<endl;
                        pos = j+1;
                    }
                }
    //            cout<<endl;
                printf("%lld
    ", ans);
                return 0;
    }
    View Code
  • 相关阅读:
    (一)Python入门-6面向对象编程:10特殊方法和运算符重载-特殊属性
    (一)Python入门-6面向对象编程:09多态
    (一)Python入门-6面向对象编程:08多重继承-mro()-super()获得父类的定义
    (一)Python入门-6面向对象编程:07面向对象三大特征(封装、继承、多态)-继承
    (一)Python入门-6面向对象编程:06私有属性和私有方法(实现封装)-@property装饰器-get和set方法-总结
    (一)Python入门-6面向对象编程:05方法没有重载-方法的动态性
    (一)Python入门-6面向对象编程:04__del__方法(析构函数)和垃圾回收机制-__call__方法和可调用对象
    python并发编程
    python学习笔记:第21天 常用内置模块之collections和time
    python学习笔记:第20天 多继承、MRO C3算法
  • 原文地址:https://www.cnblogs.com/ckxkexing/p/11219612.html
Copyright © 2011-2022 走看看