zoukankan      html  css  js  c++  java
  • 2017 Chinese Multi-University Training, BeihangU Contest

    Contest Info


    传送门

    Solved A B C D E F G H I J K L
    8 / 12 O O O - - O - Ø - Ø O Ø
    • O 在比赛中通过
    • Ø 赛后通过
    • ! 尝试了但是失败了
    • - 没有尝试

    Solutions:


    A. Add More Zero

    签到。

    Code
    #include "bits/stdc++.h"
    #define hhh cerr<<"hhh"<<endl
    #define see(x) cerr<<(#x)<<'='<<(x)<<endl
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> pr;
    inline int read() {int x=0,f=1;char c=getchar();while(c!='-'&&(c<'0'||c>'9'))c=getchar();if(c=='-')f=-1,c=getchar();while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();return f*x;}
     
    const int maxn = 3e5+7;
    const int inf = 0x3f3f3f3f;
    const int mod = 1e9+7;
     
    typedef long double ld;
     
    int main() {
        int cas=0;
        int m;
        while(cin>>m) {
            printf("Case #%d: %d
    ", ++cas, int(m*(ld(log(2))/log(10))));
        }
    }
    

    B. Balala Power!

    大数比较。

    Code
    #include "bits/stdc++.h"
    #define hhh cerr<<"hhh"<<endl
    #define see(x) cerr<<(#x)<<'='<<(x)<<endl
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> pr;
    inline int read() {int x=0,f=1;char c=getchar();while(c!='-'&&(c<'0'||c>'9'))c=getchar();if(c=='-')f=-1,c=getchar();while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();return f*x;}
     
    const int maxn = 1e5+1111;
    const int inf = 0x3f3f3f3f;
    const int mod = 1e9+7;
     
    struct P{
        int a[maxn], id;
        int & operator [] (int x) { return a[x]; }
        friend bool operator < (const P &a, const P &b) {
            for(int i=maxn-1; i>=0; --i) {
                if(a.a[i]<b.a[i]) return 1;
                else if(a.a[i]>b.a[i]) return 0;
            }
            return 0;
        }
        void init(int i) { memset(a,0,sizeof(a)); id=i; }
        ll cal(int x) {
            ll res=0, t=1;
            for(int i=0; i<maxn; ++i) {
                (res+=x*a[i]*t)%=mod;
                t=t*26%mod;
            }
            return res;
        }
    }cnt[26];
     
    int n;
    int f[26];
    string s;
     
    int main() {
        int cas=0;
        while(cin>>n) {
            for(int i=0; i<26; ++i) cnt[i].init(i);
            memset(f,0,sizeof(f));
            for(int i=1; i<=n; ++i) {
                cin>>s;
                int len=s.size();
                for(int i=0; i<len; ++i) {
                    if(i==0&&len>=1) f[s[i]-'a']=1;
                    cnt[s[i]-'a'][len-1-i]++;
                }
            }
            for(int i=0; i<26; ++i) {
                for(int j=0; j<maxn; ++j) {
                    if(cnt[i][j]>=26) {
                        cnt[i][j+1]+=cnt[i][j]/26;
                        cnt[i][j]%=26;
                    }
                }
            }
            sort(cnt,cnt+26);
            int p=0; ll ans=0;
            for(int i=0; i<26; ++i) {
                if(!f[cnt[i].id]&&!p) { p=1; continue; }
                ans=(ans+cnt[i].cal(1+i-p))%mod;
            }
            printf("Case #%d: %lld
    ", ++cas, ans);
        }
    }
    

    C. Colorful Tree

    这个题很像,可以用桶做到(O(n)),核心是利用了子数具有可减性。

    F. Function

    题意:
    给定关于(0...n-1)(0...m-1)的两个排列(a,b)
    定义函数(f)(0...n-1 ightarrow 0...m-1)的一个映射。
    计算不同的(f)个数满足(f(i)=b_{f(a_i)})

    思路:
    这类题可以将问题转化为图上环的问题。
    首先将(a,b)抽象为有向图,而(f)就相当于要在两张图中连边,并且满足(i ightarrow a_i ightarrow f(a_i) ightarrow b') 最终能够到达(f(i))
    那么问题就是图上的路径问题,发现步数很小,我们可以写作几个矩阵的乘积,每个矩阵((i,j))表示(i ightarrow j)的可行性。
    矩阵写出来就类似于这样子:

    [F=A*F*B ]

    通过右乘(B^{-1})可以得到:

    [F*B^{-1}=A*F ]

    现在已知(A,B^{-1}),求满足条件的(F)个数。
    假设(B^{-1})选定((x_1,y_1),A)选定((x_2,y_2)),那么就要满足((x_2,x_1),(y_2,y_1))都在(F)矩阵中合法。
    注意到题目要求映射关系,也就是说(F)矩阵中每一行只有一个数,列没有限制,即第二维的取值没有限制。
    注意现在所有的((x_1,y_1),(x_2,y_2))都是已知的,现在相当于要(x_2)(x_1)(y_2)(y_1)进行匹配。我们只看(x)的话会在一个环上跑,即(x_2,x_1,x_i,...,x_2),同理(y)也会在一个环上跑(注意刚刚说的图论的问题)。因为列没有要求,我们对于选择的一个(x_2),都可以任意选择一个(y_i)作为起点,但是因为要满足(x)成环,(y)在跑过若干圈之后也要成环,这样才是一组合法的方案。
    也就是说对于每个(x)的环,可以任选一个(y)的环,但要满足长度的整除关系。
    细节见代码:

    Code
    #include "bits/stdc++.h"
    #define hhh cerr<<"hhh"<<endl
    #define see(x) cerr<<(#x)<<'='<<(x)<<endl
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> pr;
    inline int read() {int x=0,f=1;char c=getchar();while(c!='-'&&(c<'0'||c>'9'))c=getchar();if(c=='-')f=-1,c=getchar();while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();return f*x;}
     
    const int maxn = 3e5+7;
    const int inf = 0x3f3f3f3f;
    const int mod = 1e9+7;
     
    int n, m;
    int a[maxn], b[maxn];
    ll fac[maxn], inv[maxn];
    ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
    ll qpow(ll a,ll k){ll s=1;while(k){if(k&1)s=s*a%mod;a=a*a%mod;k>>=1;}return s;}
    ll comb(int n, int m) {
        if(n<m||m<0||n<0) return 0;
        return fac[n]*inv[m]%mod*inv[n-m]%mod;
    }
     
    int vis[maxn], sz;
    int c[maxn];
     
    void dfs(int x, int *a) {
        vis[x]=1; sz++;
        if(!vis[a[x]]) dfs(a[x],a);
    }
     
    int main() {
        int cas=0;
        fac[0]=fac[1]=inv[0]=inv[1]=1;
        for(int i=2; i<maxn; ++i) fac[i]=i*fac[i-1]%mod;
        for(int i=2; i<maxn; ++i) inv[i]=(mod-mod/i)*inv[mod%i]%mod;
        for(int i=2; i<maxn; ++i) inv[i]=inv[i]*inv[i-1]%mod;
        while(cin>>n>>m) {
            for(int i=0; i<=n; ++i) c[i]=0;
            for(int i=0; i<n; ++i) a[i]=read();
            for(int i=0; i<m; ++i) b[read()]=i;
            for(int i=0; i<m; ++i) vis[i]=0;
            for(int i=0; i<m; ++i) if(!vis[i]) {
                sz=0, dfs(i,b);
                c[sz]+=sz;
            }
            for(int i=n; i; --i) {
                for(int j=i+i; j<=n; j+=i) {
                    c[j]+=c[i];
                }
            }
            ll ans=1;
            for(int i=0; i<n; ++i) vis[i]=0;
            for(int i=0; i<n; ++i) if(!vis[i]) {
                sz=0, dfs(i,a);
                ans=ans*c[sz]%mod;
            }
            printf("Case #%d: ", ++cas);
            printf("%lld
    ", ans);
        }
    }
    

    H. Hints of sd0061

    题意:
    给定一个随机序列(a),然后现在有(m)组询问,每组询问询问序列第(b_i)大,满足(b_i+b_jleq b_k,b_i ot ={b_j},b_i<b_k,b_j<b_k)

    思路:
    求序列第(k)大,利用kth_element可以(O(n))得到,注意到(b)有条件限制,我们可以认为(b)是以斐波纳契数列那样进行增长,所以可以直接暴力kth_element,这里我们反着来进行操作即可,因为斐波纳契数列前面的项较小的比较多,所以将kth_element更多地应用在前面比较好。
    注意到(b_i=n,i=1,2,...m),所以代码中有个细节,就是kth_element的区间范围问题,我们每次对于一个左闭右开区间进行排序,如果第(k)项为右端点会直接返回不进行操作。这样就能保证复杂度。
    代码如下:

    Code
    #include "bits/stdc++.h"
    #define hhh cerr<<"hhh"<<endl
    #define see(x) cerr<<(#x)<<'='<<(x)<<endl
    using namespace std;
    typedef unsigned int ll;
    typedef pair<int,int> pr;
    inline int read() {int x=0,f=1;char c=getchar();while(c!='-'&&(c<'0'||c>'9'))c=getchar();if(c=='-')f=-1,c=getchar();while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();return f*x;}
     
    const int maxn = 1e7+7;
    const int inf = 0x3f3f3f3f;
    const int mod = 1e9+7;
     
    int n, m;
    ll A, B, C, x, y, z;
    ll a[maxn];
    struct node {
        int val;
        int p;
        bool operator < (const node& A) const {
            return val < A.val;   
        }
    }b[105];
    ll ans[maxn];
     
    ll rng61() {
    	ll t;
    	x = x ^ (x << 16);
    	x = x ^ (x >> 5);
    	x = x ^ (x << 1);
    	t = x;
    	x = y;
    	y = z;
    	z = (t ^ x) ^ y;
    	return z;
    }
     
     
    int main() {
        ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
        int cas=0;
        while(cin>>n>>m>>A>>B>>C) {
            x=A, y=B, z=C;
            for(int i=0; i<n; ++i) {
                a[i]=rng61();
            }
            cout<<"Case #"<<++cas<<':';
            for(int i=0; i<m; ++i) {
                cin>>b[i].val;
                b[i].p = i;
            }   
            sort(b, b+m);
            int r=n;
            for(int i=m-1; i>=0; --i) {
                nth_element(a,a+b[i].val,a+r);
                ans[b[i].p]=a[b[i].val];
                r=b[i].val;
            }
            for(int i=0; i<m; ++i) cout<<' '<<ans[i];
            cout<<'
    ';
        }
    }
    

    J. Journey with Knapsack

    题意:

    [prod_{i=1}^nfrac{1-x^{i(a_i+1)}}{1-x^i}(mod x^{2n+1}) ]

    思路:
    这个乘积我们可以分子、分母单独计算。
    对于分子(prod_{i=1}^n1-x^{i(a_i+1)}),因为有(a_i>a_{i-1}),所以至多(sqrt{2n})项有用,否则在模意义下为(1)
    对于分母,可以发现很类似于拆分数的生成函数。
    接下来推式子:

    [egin{aligned} &prod_{i=1}^nfrac{1}{1-x^i}\ =&prod_{i=1}^{2n}frac{1}{1-x^i}prod_{i=n+1}^{2n}(1-x^i)\ =&P(x)prod_{i=n+1}^{2n}(1-x^i)\ =&P(x)(1-x^{n+1}-x^{n+2}-cdots-x^{2n}) end{aligned} ]

    注意上面我们都在模意义下进行,我们可以直接将(prod_{i=1}^{2n}frac{1}{1-x^i})变为(P(x))的原因是在模意义下后面的数都会变为(1),没有意义。
    最后后面那一部分我们可以维护前缀和(O(1))进行计算贡献。
    更详细的推导可以见官方题解:


    细节见代码吧:

    Code
    /*
     * Author:  heyuhhh
     * Created Time:  2020/6/5 20:43:13
     */
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <cmath>
    #include <set>
    #include <map>
    #include <queue>
    #include <iomanip>
    #include <assert.h>
    #include <functional>
    #include <numeric>
    #define MP make_pair
    #define fi first
    #define se second
    #define pb push_back
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    #define Local
    #ifdef Local
      #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
      void err() { std::cout << std::endl; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
      template <template<typename...> class T, typename t, typename... A> 
      void err(const T <t> &arg, const A&... args) {
      for (auto &v : arg) std::cout << v << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 1e5 + 5, MOD = 1e9 + 7;
     
    //p[n]=p[n-1]+p[n-2]-p[n-5]-p[n-7]...
    //广义五边形数 P[i]
    void init_p(int n, int* p) {
        for (int i = 0; i <= n; i++) {
            p[i] = 0;
        }
        auto P = [&] (int i) {
            return MP(i * (3 * i - 1) / 2, i * (3 * i + 1) / 2);
        };
        p[0] = 1;
        for (int i = 1; i <= n; i++) {
            for (int j = 1;; j++) {
                pii val = P(j);
                if (val.fi > i) break;
                int t = p[i - val.fi];
                if (val.se <= i) {
                    t += p[i - val.se];
                    if (t >= MOD) t -= MOD;
                }
                if (!(j & 1)) p[i] = (p[i] + MOD - t) % MOD;
                else p[i] = (p[i] + t) % MOD;
            }
        }
    }
     
    int n, m, _;
    int f[N];
     
    void add(int& x, int y) {
        x += y;
        if (x >= MOD) x -= MOD;   
    }
     
    void dec(int& x, int y) {
        x -= y;
        if (x < 0) x += MOD;
    }
     
    void run() {
        init_p(2 * n, f);
        for (int i = 1; i <= n; i++) {
            int x; cin >> x;
            ll t = 1ll * i * (x + 1);
            if (t > 2 * n) continue;
            for (int j = 2 * n; j >= t; j--) {
                dec(f[j], f[j - t]);
            }
        }
        int sum = 0;
        for (int i = n + 1; i <= 2 * n; i++) {
            add(sum, f[i - n - 1]);
            dec(f[i], sum);
        }
        cout << "Case #" << ++_ << ": ";
        int ans = 0;
        for (int i = 1; i <= m; i++) {
            int x; cin >> x;
            add(ans, f[2 * n - x]);
        }
        cout << ans << '
    ';
    }
     
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        while (cin >> n >> m) run();
        return 0;
    }
    

    K. KazaQ's Socks

    直接找规律即可。

    Code
    /*
     * Author:  heyuhhh
     * Created Time:  2020/5/29 13:43:59
     */
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <cmath>
    #include <set>
    #include <map>
    #include <queue>
    #include <iomanip>
    #include <assert.h>
    #include <functional>
    #include <numeric>
    #define MP make_pair
    #define fi first
    #define se second
    #define pb push_back
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    #define Local
    #ifdef Local
      #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
      void err() { std::cout << std::endl; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
      template <template<typename...> class T, typename t, typename... A> 
      void err(const T <t> &arg, const A&... args) {
      for (auto &v : arg) std::cout << v << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 1e5 + 5;
     
    ll n, k;
    int _;
     
    void run() {
        ++_;
        cout << "Case #" << _ << ": ";
        if (k <= n) {
            cout << k << '
    ';
            return;   
        }
        k -= n;
        ll t = (k + n - 2) / (n - 1);
        if (t & 1) {
            cout << (k - 1) % (n - 1) + 1 << '
    ';
        } else {
            if (k % (n - 1) == 0) {
                cout << n << '
    ';
            } else {
                cout << (k - 1) % (n - 1) + 1 << '
    ';
            }
        }
    }
     
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        while (cin >> n >> k) run();
        return 0;
    }
    

    L. Limited Permutation

    题意:
    现有排列(p),对于每个位置给定区间([l_i,r_i]),意即(i)这个位置的数为该区间最小值。
    现在问满足这个限制条件的排列个数为多少。

    思路:
    考虑构造出排列的笛卡尔树,在该树中任意一个子树结点的权值都大于当前结点。
    之后统计一下树上的拓扑序计数即可,详情可见传送门
    注意一下细节,就是树不“完全”的情况我们要判一下。
    细节见代码:

    Code
    /*
     * Author:  heyuhhh
     * Created Time:  2020/6/2 11:46:41
     */
    #include <iostream>
    #include <algorithm>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    #include <cmath>
    #include <set>
    #include <map>
    #include <queue>
    #include <iomanip>
    #include <assert.h>
    #include <functional>
    #include <numeric>
    #define MP make_pair
    #define fi first
    #define se second
    #define pb push_back
    #define sz(x) (int)(x).size()
    #define all(x) (x).begin(), (x).end()
    #define INF 0x3f3f3f3f
    #define Local
    #ifdef Local
      #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
      void err() { std::cout << std::endl; }
      template<typename T, typename...Args>
      void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
      template <template<typename...> class T, typename t, typename... A> 
      void err(const T <t> &arg, const A&... args) {
      for (auto &v : arg) std::cout << v << ' '; err(args...); }
    #else
      #define dbg(...)
    #endif
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    //head
    const int N = 1e6 + 5, MOD = 1e9 + 7;
     
    int fac[N], inv[N];
    void init() {
        fac[0] = 1;
        for (int i = 1; i < N; i++) {
            fac[i] = 1ll * fac[i - 1] * i % MOD;
        }
        inv[0] = inv[1] = 1;
        for (int i = 2; i < N; i++) {
            inv[i] = 1ll * inv[MOD % i] * (MOD - MOD / i) % MOD;
        }
    }
     
    int n, _;
    struct seg {
        int l, r;
    }a[N];
     
    void run() {
        ++_;
        for (int i = 1; i <= n; i++) {
            cin >> a[i].l;
        }
        for (int i = 1; i <= n; i++) {
            cin >> a[i].r;
        }
        vector <vector<pii>> L(n + 1);
        for (int i = 1; i <= n; i++) {
            L[a[i].l].push_back(MP(a[i].r, i));
        }
        for (int i = 1; i <= n; i++) {
            sort(all(L[i]));        
        }
        cout << "Case #" << _ << ": ";
        int ans = fac[n];
        function <int(int, int)> dfs;
        bool f = false;
        dfs = [&](int l, int r) {
            if (l > r) return 0;
            int t = sz(L[l]) - 1;
            if (t < 0) {
                f = true;
                return 0;
            }
            pii now = L[l][t];
            L[l].pop_back();
            int nr = now.fi, m = now.se;
            if (nr != r) {
                f = true;
                return 0;
            }
            int sz = 1 + dfs(l, m - 1) + dfs(m + 1, r);
            ans = 1ll * ans * inv[sz] % MOD;
            return sz;
        };
        dfs(1, n);
        if (f) ans = 0;
        cout << ans << '
    ';
    }
     
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        cout << fixed << setprecision(20);
        init();
        while (cin >> n) {
            run();
        }
        return 0;
    }
    
  • 相关阅读:
    【神经网络与深度学习】leveldb的实现原理
    【神经网络与深度学习】【CUDA开发】caffe-windows win32下的编译尝试
    【神经网络与深度学习】【CUDA开发】caffe-windows win32下的编译尝试
    【Qt开发】QString与数字类型的转换(不同进制)
    【Qt开发】QString与数字类型的转换(不同进制)
    【Qt开发】QT中用函数把float转化成QString
    【Qt开发】QT中用函数把float转化成QString
    【Qt开发】QTextEdit 外观属性设置
    【Qt开发】QTextEdit 外观属性设置
    oracle启动、关闭
  • 原文地址:https://www.cnblogs.com/heyuhhh/p/13054190.html
Copyright © 2011-2022 走看看