• 腾讯马拉松复赛第三场


      A 简单DP,状态DP[I][J] 表示第I个时间位置为J的最小花费

    View Code
    #include<stdio.h>
    #include<math.h>
    #include<stdlib.h>
    #include<string.h>
    const int INF = 0x3f3f3f3f;
    #define MIN(a,b) (a)<(b)?(a):(b)
    int dp[21][510];
    int val[21];
    int n, k;
    
    int main(){
        while( scanf("%d%d", &n,&k) != EOF){
            memset( dp, 0x3f, sizeof(dp) );
            for(int i = 0; i < k; i++)
            {
                scanf("%d", val+i );
                dp[1][val[i]] = 0;
            }
            for(int i = 2; i <= n; i++){ 
                for(int j = 0; j < k; j++){
                    scanf("%d", &val[j] );
                    for(int x = 0; x <= 500; x++)
                        dp[i][ val[j] ] = MIN( dp[i][val[j]], dp[i-1][x]+abs(x-val[j]) ); 
                }    
            }
            int ans = INF;
            for(int i = 0; i <= 500; i++)
                ans = MIN( ans, dp[n][i] );
            printf("%d\n", ans );
        }
        return 0;    
    }

      B 无奈的预处理。

    View Code
    /*
    len = 3: 1,2,6,10,
    len = 4: 0,4,5,9,
    len = 5: 3,7,8,40,50,60,
    len = 6: 11,12,20,30,80,90,
    len = 7: 15,16,70,
    len = 8: 13,14,18,19,41,  42,46,51,52,56,  61,62,66,
    len = 9: 17,21,22,26,31,  32,36,44,45,49,  54,55,59,64,65,  69,81,82,86,91,  92,96,100,101,102,103,
    len = 10: 24,25,29,34,35,39,43,47,48,53,57,58,63,67,68,71,72,76,84,85,89,94,95,99,
    len = 11: 23,27,28,33,37,38,74,75,79,83,87,88,93,97,98,
    len = 12: 73,77,78,
    */
    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    
    int Len[10];
    char ch[4][120] = {
    "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "20000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "60000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"    
    };
    
    
    int val[10][30] = {
     {0},{0},{0},{1,2,6,10},{0,4,5,9},
     {3,7,8,40,50,60},{11,12,20,30,80,90},{15,16,70},
     {13,14,18,19,41,  42,46,51,52,56,  61,62,66},
     {17,21,22,26,31,  32,36,44,45,49,  54,55,59,64,65,  69,81,82,86,91,  92,96,100,101,102,103}    
    };
    void init(){
        Len[0] = 0; Len[1] = 0; Len[2] = 0;
        Len[3] = 4; Len[4] = 4; Len[5] = 6;
        Len[6] = 6; Len[7] = 3; Len[8] = 13;Len[9] = 26;
    }
    
    int main(){
        init();
    /*    for(int i = 0; i < 10; i++){
            for(int j = 0; j < Len[i]; j++)
                printf("%d ", val[i][j] );
            puts("");
        }*/
        int T;
        scanf("%d", &T);
        for(int Case = 1; Case <= T; Case++){
            int n, m;
            scanf("%d%d", &n,&m);
            printf("Case #%d: ", Case);
            if( Len[n] < m ) puts("-1");
            else{
                int key = val[n][m-1];
                switch( key ){
                    case 100:
                        puts(ch[0]); break;
                    case 101:
                        puts(ch[1]); break;
                    case 102:
                        puts(ch[2]); break;
                    case 103:
                        puts(ch[3]); break;
                    default:
                        printf("%d\n",key);    
                }    
            }
        }    
        return 0;
    }

      

      C 题跪了。。

      对于区间[1,x] 含有 K个因子(type = 0), 含有K个非因子( type = 1 ),求解最小的X。。

       对于type = 0,  给定k,求[1,N]包含K个N的因子的最小整数. 通过N = p1^e1*...*px*ex

    使用前100以内素数枚举其次数来构造N, DFS剪枝搜索.

        CF #27 div.2 E 题 经典求法

      对于type = 1, 给定k, 求[1,N]包含N-k个因子的最小整数. 因为 N的因子数 <= .

        所以有,

        令      又因为 N >= 1, 所以 x >= 1

        则原式转换为   ( x >= 1, k <= 47777 )

        而二次函数   在区间 [1,INF] 是单调递增的. 

        因为 

        所以在这里有 

        又因为  , 

        所以有    

        因为 K < 50000, 所以我们可以通过枚举来求出N. 

        

    View Code
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<math.h>
    typedef long long LL;
    const int N = 50000; 
    const LL INF = (1ll<<62);
    int vis[N], cnt; 
    int p[15] = {2,3,5,7,11, 13,17,19,23,29, 31,37,41,43,47};
    int fact[N];
    int K;
    LL ans;
    
    void getfact(){ 
        memset( fact, 0, sizeof(fact));
        for(int i = 2; i < 49000; i++){
            int t = 0;
            for(int j = 1; j*j <= i; j++){
                if( i%j == 0 ){
                    t += 2; 
                    if( j*j == i ) t--;    
                }    
            }
            if( fact[i-t] == 0 ) fact[i-t] = i;
        }    
    }  
    void solve( int i, LL x, int n ){ 
        if( n == K && ans > x ) ans = x; 
        if( n >= K || i > 15 ) return; 
        for(int j = 1; (n*(j+1)<=K) && (ans/p[i]>=x); j++){
            x *= p[i];
            if( K%(n*(j+1)) == 0 )    solve( i+1, x, n*(j+1) );    
        }
    }  
    int main(){ 
        getfact();
        int T; 
        scanf("%d", &T);
        for(int Case = 1; Case <= T; Case++){   
            int type;
            scanf("%d%d",&type, &K);
            printf("Case %d: ", Case );
            if( type == 0 ){
                ans = INF; 
                solve( 0, 1, 1 ); 
                 if( ans == INF ) puts("INF");
                 else    printf("%I64d\n", ans ); 
            }
            else{ 
                if( fact[K] == 0 ) puts("Illegal");
                else    printf("%d\n", fact[K] );
            }    
        } 
        return 0;
    }

      D 题又跪了。。尼玛还选三点。。求最小相互距离。。除了想到暴力,没了。。。

      E 题, 贪心。从后到前,用优先队列维护满足 Di >= Bj 的花费。。。

    View Code
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<queue>
    #include<vector>
    using namespace std;
    
    const int N = 1e5+10;
    typedef long long LL;
    
    struct node{
        int d, p;    
        bool operator <( node tmp) const{
            return d > tmp.d;
        }
    }D[N];
    
    int compare( int a,int b ){
        return a > b;    
    }
    int B[N], n, m;
    
    priority_queue<int,vector<int>,greater<int> > Q;
    
    int main(){
        while( scanf("%d%d", &n,&m) != EOF){
            for(int i = 0; i < n; i++)
                scanf("%d", &B[i] );
            for(int i = 0; i < m; i++)
                scanf("%d", &D[i].d );
            for(int i = 0; i < m; i++)
                scanf("%d", &D[i].p );
            if( n > m ){
                puts("No");
                continue;    
            }
            sort( B, B+n, compare );
            sort( D, D+m );
            int idx = 0;
            while( !Q.empty() ) Q.pop();
            
            LL cost = 0;
            bool flag = true;
            for(int i = 0; i < n; i++){
                while( (D[idx].d >= B[i]) && (idx < m) ){
                    Q.push( D[idx].p );
                    idx++;    
                }
                if( Q.empty() ){
                    flag = false;
                    break;    
                }
                else{
                    int t = Q.top();  //printf("t = %d\n", t );
                    cost += t; Q.pop();    
                }
            }
            if( flag == false ) puts("No");
            else    printf("%I64d\n", cost );
        }
        return 0;    
    }

      

  • 相关阅读:
    Postgresql 常用操作
    捡回reset的未提交修改
    Excel 97-2003版本内部结构与查看方法
    【WPF】EntityframeworkCore Update注意事项
    Mac版StarUML破解方法
    Excel2016 自定义RTDServer添加方法
    apache中开启SSL设置方法
    软件开发中的常用工具
    编程风格统一配置EditorConfig
    Windows10简单启动项目添加方法
  • 原文地址:https://www.cnblogs.com/yefeng1627/p/2992316.html
Copyright © 2020-2023  润新知