• 2017 Chinese Multi-University Training, BeihangU Contest


    http://codeforces.com/gym/102253

    A

    用m个二进制位可以表示10^k,给定m,问k最大是多少

    乘一个lg2即可

    #include<iostream>
    #include<cstdio>
    #include<string>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #define fo(i,l,r) for(int i = l;i <= r;i++)
    #define ll long long
    using namespace std;
    const int maxn = 300050;
    int n;
    int main(){
        int T,i=0;
        double m;
        while(scanf("%lf",&m)!=EOF){
            i++;
            m = m*log(2)/log(10);
            printf("Case #%d: %d
    ",i,(int)floor(m));
        }
        return 0;
    }
    View Code

    K

    一个1-n的序列,每次选一个最小的放进暂存区,当暂存区有n-1个数时,下一次取数后把这n-1个数再放回序列,问第k次取的是多少

    推出一个规律:第一次一定是全部取一遍,之后每次都有一个取不到进行下一轮循环,这个取不到的数是最大的和次大的交替出现

    #include<iostream>
    #include<cstdio>
    #include<string>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #define fo(i,l,r) for(int i = l;i <= r;i++)
    #define ll long long
    using namespace std;
    const int maxn = 300050;
    ll n,k;
    int main(){
        int i = 0;
        while(scanf("%I64d%I64d",&n,&k)!=EOF){
            printf("Case #%d: ",++i);
            if(k<=n){
                printf("%I64d
    ",k);
            }else{
                k-=2;
                ll r=k/(n-1);
                ll tmp=1ll+(k%(n-1));
                if(tmp==n-1)tmp+=((r+1)%2);
                printf("%I64d
    ",tmp);
            }
        }
        return 0;
    }
    View Code

    B

    将一些字母串转换为26进制的数字,每个字母对应一个数字,要求这些字母转换成数后和最大,并且不能包含前导零

    分开每个字母计算贡献,然后排序。因为数字较大,需要自己动计算进位、比较大小

    因为不能包含前导零,如果根据排序结果,分配到0的字母对应的是前导零,就需要找到一个不是零的字母,然后不断往后换。

    #include<iostream>
    #include<cstdio>
    #include<string>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #define fo(i,l,r) for(int i = l;i <= r;i++)
    #define ll long long
    using namespace std;
    const int maxn = 100150;
    const ll mod = 1e9+7;
    int n;
    char s[maxn];
    ll val[50];
    bool isZero[50];
    struct dat{
        ll val;
        ll ss[maxn];
        int len;
        bool zo;
        bool operator < (const dat& b) const{
                for(int i = maxn-1;i>=1;i--){
                    if(ss[i]!=b.ss[i])return ss[i]>b.ss[i];
                }
            
            return ss[1]>b.ss[1];
        }
    }dats[26];
    int main(){
        ios::sync_with_stdio(false);
        int T = 0;
        while(cin>>n){
            memset(val,0,sizeof(val));
            memset(isZero,false,sizeof(isZero));
            for(int i = 0;i <= 25;i++){
                memset(dats[i].ss,0,sizeof(dats[i].ss));
                dats[i].len=0;
                dats[i].val=0;
                dats[i].zo=false;
            }
            for(int j = 1;j <= n;j++) {
                cin>>(s+1);
                int l = strlen(s + 1);
                if(l>1)dats[s[1]-'a'].zo=true;
                for (int i = l; i >= 1; i--) {
                    dats[s[i]-'a'].ss[l-i+1]++;
                    int t = l-i+1;
                    while(dats[s[i]-'a'].ss[t]==26){
                        dats[s[i]-'a'].ss[t] = 0;
                        t++;
                        dats[s[i]-'a'].ss[t]++;
                    }
                }
            }
            fo(i,0,25){
                for(int j = maxn-5;j>=1;j--){
                    dats[i].val *= 26ll;
                    dats[i].val += dats[i].ss[j];
                    dats[i].val %= mod;
                }
            }
            
            sort(dats,dats+26);
            int sheep=250;
            if(dats[25].zo){
                for(int i = 24;i >= 0;i--){
                    if(!dats[i].zo){
                        sheep=i;
                        break;
                    }
                }
                for(int i = sheep;i < 25;i++){
                    swap(dats[i],dats[i+1]);
                }
            }
            ll ans = 0;
            fo(i,0,25){
                ans = (ans + (ll)(25ll-(ll)i)*dats[i].val) % mod;
            }
            cout<<"Case #"<<++T<<": "<<ans<<endl;
        }
        return 0;
    }
    View Code

    F

    求一个n的排列A到m的排列B的映射,要求f(i)=b(f(a(i))),求方案数。

    由f(i)可以推知f(a(i)),由于是排列到排列的映射,i->a(i)->a(a(i))...最终一定会回到它自身,从而形成一个环。

    把这个环求出来,由上面的式子可以推知,不断地令i=b(i),走i对应的环的长度,最终一定要等于i,1-n的每一个位置的映射值等于满足这个条件的b(i)的数量。

    #include<iostream>
    #include<cstdio>
    #include<string>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #include<vector>
    #define fo(i,l,r) for(int i = l;i <= r;i++)
    #define ll long long
    using namespace std;
    const int maxn = 100050;
    const ll mod = 1e9+7;
    int n,m;
    int a[maxn];
    int b[maxn];
    int br[maxn][30];
    int amt[maxn];
    bool vis[maxn];
    vector<int> hasApp;
    bool dfs(int x,int fa,int deep){
        vis[x]=true;
        if(a[x]==fa){
            amt[deep]++;
        }else{
            dfs(a[x],fa,deep+1);
        }
    }
    bool canCir(int x,int y){
        int k = 0;
        int oy = y;
        while(x){
            if(x&1)y = br[y][k];
            k++;
            x >>= 1;
        }
        //cout<<x<<" "<<y<<" "<<oy<<endl;
        return oy == y;
    }
    int main(){
        int T = 0;
        while(scanf("%d%d",&n,&m)!=EOF){
            fo(i,0,n-1)scanf("%d",&a[i]);
            fo(i,0,m-1)scanf("%d",&b[i]);
            memset(amt,0,sizeof(amt));
            memset(vis,0,sizeof(vis));
            hasApp.clear();
            fo(i,0,m-1){
                br[b[i]][0] = i;
            }
            fo(k,1,22){
                fo(i,0,m-1){
                    br[i][k] = br[br[i][k-1]][k-1];
                }
            }
            fo(i,0,n-1){
                if(!vis[i]) dfs(i,i,1);
            }
            ll ans = 1;
            fo(i,1,n){
                if(amt[i]) hasApp.push_back(i);
            }
            int sz = hasApp.size();
            for(int i = 0;i < sz;i++){
                ll ansi = 0;
                fo(j,0,m-1){
                    if(canCir(hasApp[i],j)){
                        ansi++;
                    }
                }
                while(amt[hasApp[i]]){
                    amt[hasApp[i]]--;
                    ans = (ans*ansi) % mod;
                }
            }
            printf("Case #%d: ",++T);
            printf("%I64d
    ",ans);
        }
        return 0;
    }
    View Code

    L

    求1-n的排列的个数,其中第i个要求是(li,ri)的所有子区间的最小值都是pi,其他包含i的区间的最小值都不是p。

    首先,如果当前考虑的区间是(l,r),则一定有一个约束是包含整个区间的,我们把这个区间对应的位置i找出来,然后递归他的左边区间和右边区间。

    此时,左区间和右区间是不相关的,没有第二个跨越这两个区间的约束,两个区间的答案可以用组合数计算。

    如何快速找到包含整个区间的约束?将区间排序即可。

    #include<iostream>
    #include<cstdio>
    #include<string>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #include<vector>
    #define fo(i,l,r) for(int i = l;i <= r;i++)
    #define ll long long
    using namespace std;
    const int maxn = 1000050;
    const ll mod = 1e9+7;
    inline ll read(){
        ll x = 0, f = 1;
        char ch = getchar();
        while (ch < '0' || ch > '9'){
            if (ch == '-')
                f = -1;
            ch = getchar();
        }
        while (ch >= '0' && ch <= '9'){
            x = x * 10 + ch - '0';
            ch = getchar();
        }
        return x * f;
    }
    struct seg{
        int l;
        int r;
        int p;
        friend bool operator < (seg a,seg b){
            if(a.l!=b.l) return a.l < b.l;
            return a.r > b.r;
        }
    }s[maxn];
    int n;
    int nowpos;
    ll fac[maxn];
    ll inv[maxn];
    ll C(ll n,ll m){
        return fac[n]*inv[m]%mod*inv[n-m]%mod;
    }
    ll dfs(int l,int r){
        if(l != s[nowpos].l || r != s[nowpos].r) return 0;
        int mid = s[nowpos].p;
        nowpos++;
        ll ansl=1,ansr=1;
        if(l<mid) ansl = dfs(l,mid-1);
        if(r>mid) ansr = dfs(mid+1,r);
        return ansl*ansr%mod*C(r-l,mid-l)%mod;
    }
    int main(){
        int T = 0;
        fac[0]=fac[1]=1;
        fo(i,2,maxn-1){
            fac[i] = (fac[i-1]*i)%mod;
        }
        inv[0]=inv[1] = 1;
        fo(i,2,maxn-1){
            inv[i]=(mod-(mod/i))*inv[mod%i]%mod;
        }
        fo(i,2,maxn-1){
            inv[i] = (inv[i]*inv[i-1])%mod;
        }
        while(scanf("%d",&n)!=EOF){
            fo(i,1,n){
                s[i].p=i;
                s[i].l=read();
            }
            fo(i,1,n){
                s[i].r=read();
            }
            sort(s+1,s+1+n);
            nowpos=1;
            ll ans=dfs(1,n);
            printf("Case #%d: ",++T);
            printf("%I64d
    ",ans);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Guns项目整体结构
    基于事件的NIO多线程服务器
    Reactor模式和NIO
    ConcurrentHashMap之实现细节
    C 语言的前世今生
    Netty系列之Netty高性能之道
    java synchronized详解
    生产者/消费者模式
    当spring 容器初始化完成后执行某个方法
    Linux系统管理员需要知道的16个服务器监控命令
  • 原文地址:https://www.cnblogs.com/hyfer/p/11139510.html
Copyright © 2020-2023  润新知