腾讯马拉松复赛第三场

 

  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;    
}

 

  

posted @ 2013-03-31 21:23  yefeng1627  阅读(201)  评论(0编辑  收藏  举报

Launch CodeCogs Equation Editor