A
思路:01背包,尽可能装满背包,并且价值最大。只需要加上一个判断条件,保证每次都能够将 j 值装满。
Code:
#include
#define LL long long
#define INF 0x3f3f3f3f
using namespace std;
const int AX = 1e6+66;
int v[AX];
LL w[AX];
LL dp[AX];
int main(){
int T;
int n , V;
scanf("%d",&T);
while( T-- ){
scanf("%d%d",&n,&V);
for( int i = 1 ; i <= n ; i++ ){
scanf("%lld",&w[i]);
}
for( int i = 1 ; i <= n ; i++ ){
scanf("%d",&v[i]);
}
memset( dp , 0 , sizeof(dp) );
for( int i = 1 ; i <= n ; i++ ){
for( int j = V ; j >= v[i] ; j-- ){
if( dp[j-v[i]] || j == v[i] )
dp[j] = max( dp[j] , dp[j-v[i]] + w[i] ) ;
}
}
int j = V;
int VV = 0;
LL ibest = 0;
for( int i = V ; i > 0 ; i-- ){
if(dp[i] > ibest){
ibest = dp[i];
VV = i;
}
}
printf("%lld %d\n",ibest,VV);
}
return 0 ;
}
C
题意:给你一个数字 ,你的任务是找一个最小的正整数 N,使得它的数位之积等于 Q
,如果不存在,请输出-1.
思路:每位只可能是2-9(1除外),每次尽可能大的取因子(2-9)如果不能整除就输出-1,
最后排序输出即可。
坑点就是0输出10,而不是-1.。。。。
Code:
#include
#define LL long long
using namespace std;
const int AX = 1e4+6;
int res[AX];
int n;
int cnt;
int main(){
int T;
scanf("%d",&T);
while( T-- ){
scanf("%d",&n);
if( n == 1 ){
printf("1\n"); continue;
}else if( n == 0 ){
printf("10\n"); continue;
}
cnt = 0;
int falg = 1 ;
while( n > 1 ){
int f = 0 ;
for( int i = 9 ; i >= 2 ; i-- ){
while( n % i == 0 ){
res[cnt ++ ] = i;
n /= i ;
f = 1 ;
}
}
if( !f && n > 1 ) { falg = 0 ; break; }
}
if( falg == 0 ){
printf("-1\n");
continue;
}
sort( res , res + cnt ) ;
for(int i = 0 ; i < cnt ; i++ ){
printf("%d",res[i]);
}printf("\n");
}
return 0;
}
D
题意:每次将最小的两个合并,并且编号采用较小的,给出m个询问,第t次之后Q的编号。
思路:并查集+模拟
优先队列id排序写反了,wa了超级久!!!
Code:
#include
#define LL long long
#define INF 0x3f3f3f3f
using namespace std;
const int AX = 1e6+66;
int t, Q;
struct Node{
int id ;
int v;
bool friend operator < ( const Node &a , const Node &b ){
return ( a.v > b.v || ( a.v == b.v && a.id > b.id ) );
}
}a[AX];
int pre[AX];
int find( int x ){
//return x == pre[x] ? pre[x] : pre[x] = find(pre[x]);
if( x == pre[x] ) return pre[x];
return pre[x] = find(pre[x]);
}
int main(){
int T;
scanf("%d",&T);
int n , m ;
priority_queue q;
while( T-- ){
while( !q.empty() ) q.pop();
scanf("%d%d",&n,&m);
for( int i = 1 ; i <= n ; i++ ){
scanf("%d",&a[i].v);
a[i].id = i ;
pre[i] = i ;
q.push(a[i]);
}
int j = 0 ;
for( int i = 0 ; i < m ; i++ ){
scanf("%d%d",&t,&Q);
for( ; j < t ; j++ ){
Node x = q.top();
q.pop();
Node y = q.top();
q.pop();
Node tmp ;
tmp.v = x.v + y.v;
tmp.id = min( x.id , y.id );
q.push(tmp);
int xx = find(x.id);
int yy = find(y.id);
if( xx < yy ){
pre[yy] = xx;
}else pre[xx] = yy;
}
//cout << find(Q) << endl;
printf("%d\n",find(Q));
}
}
return 0 ;
}
F
题意:输出相反数。
思路:最坑的题。。用java才过。
Code:
import java.util.*;
import java.math.*;
public class Main{
public static void main(String[] args){
Scanner cin = new Scanner(System.in);
BigDecimal a , b , c ;
int m;
m = cin.nextInt();
while(m>0){
m = m - 1 ;
a = cin.nextBigDecimal();
b = new BigDecimal("0");
b = b.subtract(a) ;
System.out.println(b);
}
}
}
G
题意:从1到n,每次可能往回走,也可能往前走,问距离期望的平方。
思路:随机走在二维上距离的期望是n,在一维上距离 期望的平方 和二维的一样也是n
Code:
#include
#define LL long long
using namespace std;
int main(){
int T;
scanf("%d",&T);
int n ;
while( T-- ){
scanf("%d",&n);
printf("%.6lf\n",(double)n);
}
return 0;
}
H
题意:就是给n个点,m条边,这个边是每条路的高度(0,1,2),0不能走,可以给0添加高度值2,1,给1添加1,0。
要求路径必须是只能上升一次,也就是111222这样的1,2都可以没有。。问最少添加多少高度可以从1到达n。
思路:路径是111222这样的,所以从1开始将只走高度为1的边,0加上1,2不走。
再从n走向1只走高度为2的,0加上2,1加上1.然后取二者加和的最小值。
Code:
#include
#define LL long long
#define INF 0x3f3f3f3f
using namespace std;
const int AX = 4e6+66;
typedef pair<int,int>P;
struct Node{
int v , h ;
int next1 ;
}G[AX];
int head[AX];
int tot ;
void addEdge( int u , int v , int h ){
G[++tot].v = v ; G[tot].h = h ; G[tot].next1 = head[u];
head[u] = tot ;
G[++tot].v = u ; G[tot].h = h ; G[tot].next1 = head[v];
head[v] = tot ;
}
int vis[AX];
int n , m ;
int dis[AX];
int dis_inv[AX];
priority_queue< P , vector , greater >q;
void dijstra(){
memset( dis, INF , sizeof(dis) ) ;
q.push(P(0,1));
dis[1] = 0 ;
while( !q.empty() ){
int u = q.top().second;
int val = q.top().first;
q.pop();
if( vis[u] ) continue;
vis[u] = 1 ;
if( val > dis[u] ) continue;
for( int i = head[u] ; ~i ; i = G[i].next1 ){
int v = G[i].v ;
if( G[i].h > 1 ) continue;
if( dis[v] > dis[u] + 1 - G[i].h ){
dis[v] = dis[u] + 1 - G[i].h ;
q.push(P( dis[v] , v ));
}
}
}
}
void dijstra_inv(){
memset( dis_inv, INF , sizeof(dis_inv) ) ;
q.push(P(0,n));
dis_inv[n] = 0 ;
while( !q.empty() ){
int u = q.top().second;
int val = q.top().first;
q.pop();
if( vis[u] ) continue;
vis[u] = 1 ;
if( val > dis_inv[u] ) continue;
for( int i = head[u] ; ~i ; i = G[i].next1 ){
int v = G[i].v ;
if( dis_inv[v] > dis_inv[u] + 2 - G[i].h ){
dis_inv[v] = dis_inv[u] + 2 - G[i].h ;
q.push(P( dis_inv[v] , v ));
}
}
}
}
int main(){
int T;
scanf("%d",&T);
int u , v , h ;
while( T-- ){
tot = 0 ;
memset( head , -1 , sizeof(head) );
memset( vis , 0 , sizeof(vis) );
scanf("%d%d",&n,&m);
for( int i = 0 ; i < m ; i++ ){
scanf("%d%d%d",&u,&v,&h);
addEdge( u , v , h );
}
dijstra();
memset( vis , 0 , sizeof(vis) );
dijstra_inv();
int res = INF;
for( int i = 1 ; i <= n ; i++ ){
res = min( res , dis[i] + dis_inv[i] );
}
printf("%d\n",res);
}
return 0 ;
}