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剪枝搜索.
对于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; }