zoukankan      html  css  js  c++  java
  • 2013517 训练赛总结

    训练赛链接: http://openoj.awaysoft.com:8080/judge/contest/view.action?cid=424#overview

    题目来源: The 10th Zhejiang Provincial Collegiate Programming Contest

     还是想吐嘈 ZOJ的题目描述,与模拟题的恶心程度........

    Applications

       背景是ACM集训队选拔,根据OJ题数,区域赛获奖,CF/TC排名, 还有个性别,  注意的地方是CF不满三场不计算.

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<vector>
    #include<string>
    #include<map>
    #include<algorithm>
    using namespace std;
    
    
    const int N = 1010;
    
    bool isprime(int x){
        for(int i = 2; i*i <= x; i++)
            if( x%i == 0 ) return false;
        return true;
    }
    int n, m;
    bool cmp(int a,int b){
        return a > b;
    }
    
    map< string, int > regional;
    map< int, double > tiku;
    const double esp = 1e-8;
    int sign(double x){
        return x < -esp ? -1 : (x >esp);
    }
    struct Peason{
        string name;
        string team_name;
        string sex;
        double score;
        vector<int> problem;
        vector<int> cf;
        void read(){
            // init
            problem.clear(); cf.clear();
            char tmp[50];
            int oj_num, cf_num, x;    
            scanf("%s",tmp); name = tmp;
            scanf("%s",tmp); team_name = tmp;
            scanf("%s",tmp); sex = tmp;
            scanf("%d %d",&oj_num,&cf_num );    
            for(int i = 0; i < oj_num; i++){
                scanf("%d", &x);
                problem.push_back(x);
            }    
            for(int i = 0; i < cf_num; i++){
                scanf("%d", &x);
                cf.push_back(x);
            }    
        }
        void modify(){
            score = 0;    
            if( regional.count( team_name ) ){
                int d = regional[team_name];    
                if( d == 1 ) score += 36;
                else if( d == 2 ) score += 27;
                else if( d == 3 ) score += 18;
            }     
            for(int i = 0; i < (int)problem.size(); i++){
                int d = problem[i];    
                if( tiku.count(d) != 0 ) score += tiku[d];
                else if( isprime(d) ) score += 1;
                else score += 0.3;
            }     
            if( cf.size() >= 3 ){    
                sort( cf.begin(), cf.end(), cmp );    
                int r = cf[2];
                score += max( 0.0, (r-1200)/100. )*1.5;
            }    
            if( sex == "F" ) score += 33;
    
        }
        bool operator < (const Peason &tmp) const{
            if( sign(score-tmp.score) != 0 ){
                return sign(score-tmp.score) == 1;    
            }    
            else return name < tmp.name;    
        } 
    }p[N];
    
    
    void gao(){
        scanf("%d%d", &n, &m);
        // tiku info    
        int pro_n, x;
        scanf("%d", &pro_n);
        tiku.clear();
        for(int i = 0; i < pro_n; i++){
            scanf("%d", &x);
            tiku[x] = 2.5;
        }
        scanf("%d", &pro_n);
        for(int i = 0; i < pro_n; i++){
            scanf("%d", &x);
            tiku[x] = 1.5;
        }
        // regional    
        int team_num, rank;
        char str[N];
        scanf("%d", &team_num );
        regional.clear();    
        for(int i = 0; i < team_num; i++){
            scanf("%s %d", str, &rank );
            regional[str] = rank;
        }
        //peason
        for(int i = 0; i < n; i++)
            p[i].read(), p[i].modify();
    
        sort( p, p+n );
        for(int i = 0; i < m; i++)
            printf("%s %.3lf\n", p[i].name.c_str(), p[i].score );
    }
    
    int main(){ 
        int T;
        scanf("%d", &T);
        while( T-- ){
            gao();
        }
        return 0;
    }
    View Code

     

    Break Standard Weight

      已知a,b,枚举c, 取值范围 [1,a/2 ],  然后枚举天平左右放置情况,   再做一次(b,a)就好.

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<set>
    #include<map>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    
    const int N = 500;
    
    bool vis[N];
    int w[3];
    int cao(int a,int b,int c){
        memset(w,0,sizeof(w));
        memset(vis,0,sizeof(vis));
        vis[0] = 1;
        int cnt = 0;    
        for(int i = 0; i <= 2; i++)
        {
            w[i] += a;
            for(int j = 0; j <= 2; j++)
            {
                w[j] += b;    
                for(int k = 0; k <= 2; k++)
                {
                    w[k] += c;
                    int t = abs( w[1]-w[2] );
                    if( !vis[t] )
                        vis[t] = 1, cnt += 1;
                    w[k] -= c;
                }
                w[j] -= b;    
            }
            w[i] -= a;    
        }
        return cnt;
    }
    int gao(int a,int b){
        int res = 0;
        for(int c = 1; c <= a/2; c++){
            // a, b, c
            res = max( res, cao( a-c, c, b ) );    
        } 
        return res;
    }
    int main(){
        int T;
        scanf("%d", &T);
        while( T-- ){
            int x, y;
            scanf("%d%d", &x,&y);
            printf("%d\n", max( gao(x,y), gao(y,x) ) );
        }
        return 0;
    }
    View Code

    Calculate Prime S

      首先通过枚举子集数量k, 得到Sn计算式子, Sn = \sum C( n-k+1, k ),  然后可看出来(输出前面一部分)是fibonacci数. 

      而对于 S 是prime的定义, 其实就是 Fibonacci素数,  对于fibonacci素数,这里可以得出两个性质:

        1.  从第5项(前五项为:1,1,2,3,5) 开始, 项数为素数,则Fi为Fib素数. 可通过 假定Fi%M, 然后由 Fk = 0, 则 F_(t*k) = 0, 得出.

        2.  Fibonacci数 Fi % M, 必有循环节, 且循环节长度是 O(M), 不太会证明.  -_-..据说要部分代数.

      然后解题思路是, 求出第k个S prime, 其实就是 第k个素数(前两项2,3,应该替换成3,4), 然后 Sn从P_k开始枚举, 当出现 Sn%x = 0, 则找到了对应的Sn.但是最终结果所求为 (Sn/x)%M,  可以转换成  Sn%(x*M).  然后最后再除以一个 X即可.  求 Fibonacci数 通过构造转置矩阵,快速幂求即可.

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    
    typedef long long LL;
    const int N = (int)2e7+10;
    
    int prime[N/10], p_num;
    bool vis[N];
    void GetPrime(){
        memset(vis,0,sizeof(vis));
        vis[1] = 1; p_num = 1;
        for(int i = 2; i < N; i++){
            if( !vis[i] ) prime[p_num++] = i;
            for(int j = 1; (j<p_num)&&(prime[j]*i<N); j++){
                vis[ prime[j]*i ] = 1;
                if( i%prime[j] == 0 ) break;
            }
        }
        prime[1] = 3, prime[2] = 4;
        // p_num = 1.2 * 10^6    
    //    printf("%d\n", p_num );
    }
    
    struct Matrix{
        LL mat[2][2];
        void zero(){memset(mat,0,sizeof(mat));}
        void unit(){ zero(); mat[0][0]=mat[1][1]=1; }    
    };
    Matrix mult( Matrix A, Matrix B, int mod ){
        Matrix C; C.zero(); 
        for(int i = 0; i < 2; i++){
            for(int k = 0; k < 2; k++)
                for(int j = 0; j < 2; j++)
                    C.mat[i][j] = (C.mat[i][j]+A.mat[i][k]*B.mat[k][j])%mod;
        }
        return C;
    }
    Matrix Pow( Matrix X, int n, int mod ){
        Matrix res; res.unit(); 
        while( n ){
            if( n&1 ) res = mult(res,X,mod);
            X = mult(X,X,mod);
            n >>= 1;
        }
        return res;
    }
    
    
    Matrix A, T;
    void init_Matrix(){
        A.mat[0][0] = A.mat[1][0] = 1; A.mat[0][1] = A.mat[1][1] = 0;
        T.mat[0][0] = 0; T.mat[0][1] = T.mat[1][0] = T.mat[1][1] = 1;
    }
    void print( Matrix t ){
        for(int i = 0; i < 2; i++){
            for(int j = 0; j < 2; j++)
                printf("%lld ", A.mat[i][j] );
            puts("");
        }
    }
    void solve(){
        int k, x, m;
        scanf("%d%d%d", &k, &x, &m);
        int k_idx = prime[k], s_idx = k_idx;
    //    printf("k_idx = %d\n", k_idx );    
        init_Matrix();    
        A = mult( Pow(T,k_idx-1,x), A, x ); 
    //    print(A);    
        for( ;; s_idx++ ){
            if( A.mat[0][0] == 0 ) break;
            //printf("A.mat[0][0] = %lld, [1][0] = %lld\n", A.mat[0][0], A.mat[1][0] );    
            A = mult( T, A, x ); 
        }    
        //printf("s_idx = %d\n", s_idx );    
        init_Matrix();
        A = mult( Pow(T,s_idx-1,x*m), A, x*m );
        printf("%lld\n", A.mat[0][0]/x );
    }
    int main(){
        GetPrime();
        int T;
        scanf("%d", &T);
        while( T-- ){
            solve();    
        }
        return 0;
    }
    View Code

    Density of Power Network

      题目描述那副图好复杂.不过题意和图没多大关系. 统计不重复的边.然后除以顶点N即可. 

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<vector>
    #include<algorithm>
    using namespace std;
    
    const int N = 550;
    
    bool mp[N][N];
    int a[N], b[N];
    
    
    int main(){
        freopen("1.in", "r", stdin);
    
        int T;
        scanf("%d", &T);
        while( T-- ){
            int n, m;
            scanf("%d%d",&n,&m);
            memset(mp,0,sizeof(mp));
            for(int i = 0; i < m; i++)
                scanf("%d", &a[i]);
            for(int i = 0; i < m; i++)
                scanf("%d", &b[i]);
            for(int i = 0; i < m; i++)
                mp[ a[i] ][ b[i] ] = mp[ b[i] ][ a[i] ] = 1;
            int cnt = 0;    
            for(int i = 1; i <= n; i++)
                for(int j = i; j <= n; j++)
                    cnt += mp[i][j];
            printf("%.3lf\n", 1.0*cnt/n );
        }
        return 0;
    }
    View Code

    Egg Painting

      计算几何只会水题版本...太神了不太会...

    Friends

      N才100, 枚举两个没关联的, 然后看其相同朋友是否大于等于K, 若是则连接.  要注意的是, 连接后还有可能给其他人造成影响.所以需要重复的搞. 第二组样例看的出来.

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<vector>
    #include<algorithm>
    using namespace std;
    
    const int N = 110;
    
    bool mp[N][N];
    vector<int> Q[N];
    int n, m, k;
    
    int main(){
        freopen("1.in","r",stdin);
        int T;
        scanf("%d", &T);
        while( T-- ){
            scanf("%d%d%d", &n,&m,&k);
            memset( mp, 0, sizeof(mp));
            for(int i = 0; i < n; i++) Q[i].clear();    
            for(int i = 0; i < m; i++){
                int a, b;
                scanf("%d%d",&a,&b);
                mp[a][b] = mp[b][a] = true;
                Q[a].push_back(b);
                Q[b].push_back(a);
            }
            int res = 0;    
            while( 1 ){    
            int cnt = 0;    
                for(int a = 0; a < n; a++){
                for(int b = a+1; b < n; b++){
                    if( mp[a][b] == false){
                        int t = 0;    
                        for(int i = 0; i < (int)Q[a].size(); i++){
                            int c = Q[a][i];
                            if( mp[b][c] == true ) t++;
                        }            
                        if( t >= k ){
                            mp[a][b] = mp[b][a] = true;
                            Q[a].push_back(b);
                            Q[b].push_back(a);
                            cnt++;    
                        }    
                    }    
                }    
            }    
                res += cnt;    
                if( cnt == 0 ) break;    
            }    
            printf("%d\n", res );    
        }
        return 0;
    }
    View Code

    Give Me Your Hand

      概率DP一直很渣.

    Hard to Play

      别想太复杂.. 可以证明, 因为次数累积, 则分数大的放后面连续必定最大,   反之则最小.

    #include<cstdio>
    int main(){
        int T;
        scanf("%d", &T);
        while( T-- ){
            int A, B, C;
            scanf("%d%d%d", &A,&B,&C);
            int res = 0, ans = 0;
            for(int i = 1, t = 0; i <= A+B+C; t++, i++ )
                if( i > B+C ) res += 300*( t*2+1 );    
                else if( i > C) res += 100*( t*2+1 );
                else res += 50*( t*2+1 );
            for(int i = 1, t = 0; i <= A+B+C; t++, i++ )
                if( i <= A ) ans += 300*( t*2+1 );    
                else if( i <= A+B ) ans += 100*( t*2+1 );
                else ans += 50*( t*2+1 );
            printf("%d %d\n", ans, res );    
        }
        return 0;
    }
    View Code

    In 7-bit

      神描述. 虽然我没看懂...但是队伍中有jian1573这样的大神.....

    #include <iostream>
    #include <cmath>
    #include <cstring>
    #include <cstdio>
    #include <string>
    #include <stdlib.h>
    #include <algorithm>
    using namespace std;
    typedef long long LL;
    const LL Mod= 1e9+7;
    const int M=3000050;
    char s[M];
    int T;
    int main( )
    {
        scanf("%d", &T);
        getchar();
        while(T--){
            gets(s);
            int len=strlen(s);
            if (len == 0) {
                puts("00");
                continue;
            }
            int t=len;
            while(t){
                int ans= (t&0x7f);
                t >>= 7;
                if( t>0 ) ans |= 0x80;
                printf("%02X",ans);
            }    
            for( int i=0; i<len; ++ i ){
                printf("%02X", s[i]);    
            }
            puts("");
        }
        return 0;
    }
    View Code

    Java Beans

      围成一圈,求连续M个最大值....N <= 100...M <= 100... 除了暴力我真心不知道还能干嘛.

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    
    const int N = 210;
    const int inf = 0x3f3f3f3f;
    int n, m;
    int a[N];
    
    int main(){
        int T;
        scanf("%d", &T);
        while(T--){
            scanf("%d%d", &n,&m);
            for(int i = 0; i < n; i++)
                scanf("%d", &a[i]);
            
            int res = 0;
            for(int i = 0; i < n; i++){
                int t = 0;    
                for(int j = 0; j < m; j++){
                    t += a[ (i+j)%n ];
                }    
                res = max( res, t );    
            }
            printf("%d\n", res);    
        }
        return 0;
    }
    View Code

    Kindergarten Election

      正面贪心, 无法得到正确解.  变量过多, 通过枚举部分变量然后确定其他变量.  

      枚举 1获得票数x. 然后 处理其他票数大于X的,降至X-1,则必然只能加到1去. 1票数超过x则不合法, 若1的小于x,则再贿赂最小花费的人,加到x..然后求出最小的cost.即是最终答案.

    有个地方我们没有处理, 就是当1获得x票,其他人都是x-1票.这个时候,因为1本身要投一票给别人. 可能会有其他N-1个都含有X-1票,这时候会发现1拿X票不一定赢, 其实简单推下就能发现这种情况是不存在的, 若存在, 则这时候有 x + (N-1)*(x-1) + 1 = N , 然后变换下得到  x = 2 - 2/N,  因为N>=3,  则 x必定为浮点数,而非整数. 所以此时的X是不存在的. 所以此情况无需考虑. 然后代码写起来就很短了.

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cstdlib>
    using namespace std;
    
    const int N = 200;
    const int inf = 0x3f3f3f3f;
    int f[N], c[N], d[N];
    int n;
    int tf[N], td[N];
    bool vis[N];
    
    int GetMax(){ // temp
        int t = -1;    
        for(int i = 2; i <= n; i++)
            t = max( t, td[i] );
        return t;
    }
    int update(int x){ // tmp_father and tmp_depth
        td[ tf[x] ]--;
        td[1]++;
        tf[x] = 1;
        return c[x];
    }
    int maintain(int tar){
        int cost = 0;    
        bool flag = false;        
        for(int i = 2; i <= n; i++){
            if( td[i] < tar-1 ) 
                flag = true;
        }
        if( flag ) return cost;
        else{
            int t = inf, pos;
            for(int i = 2; i <= n; i++){
                if( (td[ tf[i] ] == tar-1) && (t > c[i]) )
                    t = c[i], pos = i;
            }
            cost += update(pos);        
            return cost;    
        }
    }    
    int cao(int tar){
        int cost = 0, k;
        for(int i = 1; i <= n; i++)
            td[i] = d[i], tf[i] = f[i];
        k = GetMax();
        while( k >= tar ){
            int t = inf, pos;
            for(int i = 2; i <= n; i++){
                if( (tf[i]!=1) && (td[tf[i]]>=tar) && (t>c[i]) )    
                        t = c[i], pos = i;
            }
            cost += update( pos );    
            k = GetMax();
        }    
        if( td[1] > tar ) return inf;
        else{
            while( td[1] < tar ){
                int t = inf, pos;
                for(int i = 2; i <= n; i++)
                    if( (tf[i]!=1) && (t > c[i]) )
                        t = c[i], pos = i;
                cost += update(pos);
            }    
        //    cost += maintain( tar );        
            return cost;    
        }
    }
    int gao(){
        int res = inf;
        for(int i = 2; i <= n-1; i++){
            int t = cao(i);
        //    printf("i = %d, t = %d\n", i, t);
            res = min( res, t );
        }    
        return res;
    }
    int main(){
        int T;
        scanf("%d", &T);
        while( T-- ){
            scanf("%d", &n);
            memset( d, 0, sizeof(d));
            memset( c, 0, sizeof(c)); 
            for(int i = 2; i <= n; i++){
                scanf("%d", &f[i] );
                d[ f[i] ]++;
            }
            for(int i = 2; i <= n; i++){
                scanf("%d", &c[i] );    
            }    
            printf("%d\n", gao() );    }
        return 0;
    }
    View Code
  • 相关阅读:
    IOS-SQLite3的封装
    IOS-SQLite3
    IOS-真机相关
    IOS-将任意对象存进数据库
    IOS-支付宝
    IOS-推送通知
    iOS-证书真机调试
    iOS-免证书真机调试
    iOS-沙盒路径
    Android之发送短信的两种方式
  • 原文地址:https://www.cnblogs.com/yefeng1627/p/3085678.html
Copyright © 2011-2022 走看看