腾讯马拉松复赛第三场

 

  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;    

}

 

  

你可能感兴趣的:(腾讯)