2013 Multi-University Training Contest 1
2013-07-27 02:05
399 查看
这场比赛。。。伤心了
A - Harvest Moon(HDU4600)
题意:给你好多种种子,每种都有价格和收益。再给你一片地,问你只选一种种子播种的最大收益。
思路:枚举每种种子然后模拟。我很煞笔的开了个数组记录大小为i的土地的数量。TLE到死,最后很猥琐的除GCD,950ms水过。
C - Partition(HDU 4602)
这题猥琐的算前几项然后搜的公式
题意:给你一颗树,想象一个小球从根往下落,问你小球从根到某点的概率。
思路:首先,将路径统计一下,分为左路径和右路径,然后分别统计有多少大于X的。统计我用的傻逼树。
G -
Occupy Cities(HDU 4606)
floyd+二分+最小路径覆盖
#include<iostream>
#include<string.h>
#include<stdio.h>
#include<string>
#include<math.h>
#define oo 1e9
#define eps 1e-8
#define maxn 500
#define maxm 10000
using namespace std;
struct Point
{
int u,v;
Point(){}
Point(double a,double b):u(a),v(b){}
Point operator - (const Point p) {return Point(u-p.u,v-p.v);}
}p[maxn],wall[maxn];
double ma[maxn][maxn];
int map[maxn][maxn],match[maxn],id[maxn];
bool vis[maxn];
int n,m,PP,T,N,M;
int dlcmp(double x) {return x<-eps?-1:x>eps;}
double sqr(double x) {return x*x;}
double dist(Point a,Point b) {return sqrt(sqr(a.u-b.u)+sqr(a.v-b.v));}
double cross(Point a,Point b) {return a.u*b.v-b.u*a.v;}
int segment_intersect(Point s1,Point e1,Point s2,Point e2)
{
if (max(s1.u,e1.u)>min(s2.u,e2.u)&&max(s2.u,e2.u)>min(s1.u,e1.u)&&max(s1.v,e1.v)>min(s2.v,e2.v)&&max(s2.v,e2.v)>min(s1.v,e1.v)&&
dlcmp(cross(e1-s1,s2-s1))*dlcmp(cross(e1-s1,e2-s1))<0&&dlcmp(cross(e2-s2,s1-s2))*dlcmp(cross(e2-s2,e1-s2))<0)
return 1;
else
return 0;
}
bool NO( int x, int y )
{
for ( int i = 1; i <= m; ++i )
{
if ( segment_intersect(p[x],p[y],wall[i],wall[i+m]) ) return 0;
}
return 1;
}
double makemap()
{
for ( int i = 1; i <= N; ++i )
for ( int j = 1; j <= N; ++j )
if ( i != j ) ma[i][j] = oo;
else ma[i][j] = 0;
for ( int i = 1; i <= N; ++i )
for ( int j = 1; j < i; ++j )
if ( NO(i,j) )
{
ma[i][j] = min(ma[i][j],dist(p[i],p[j]));
ma[j][i] = ma[i][j];
}
for ( int k = 1; k <= N; ++k )
for ( int i = 1; i <= N; ++i )
if ( k != i )
for ( int j = 1; j <= N; ++j )
if ( i !=j && k != j && ma[i][j] > ma[i][k] + ma[k][j] && ma[i][k] < oo && ma[k][j] < oo )
ma[i][j] = ma[i][k]+ma[k][j];
double maxx = 0;
for ( int i = 1; i <= n; ++i )
for ( int j = 1; j < i; ++j )
if ( maxx < ma[i][j] ) maxx = ma[i][j];
return maxx;
}
int find( int x )
{
for ( int i = 1; i <= n; ++i )
if ( map[x][i] == 1 && vis[i] == 0 )
{
vis[i] = 1;
if ( match[i] == 0 || find(match[i]) )
{
match[i] = x;
return 1;
}
}
return 0;
}
bool can( double mid )
{
memset(map,0,sizeof(map));
for ( int i = 1; i <= n; ++i )
for ( int j = 1; j <= n; ++j )
if ( id[i] < id[j] &&ma[i][j]-mid <=0 )
map[i][j] = 1;
memset(match,0,sizeof(match));
int res = 0;
for ( int i = 1; i <= n; ++i )
{
memset(vis,0,sizeof(vis));
res += find(i);
}
if ( n - res <= PP ) return 1;
else return 0;
}
int main()
{
int u;
scanf("%d",&T);
while ( T-- )
{
scanf("%d%d%d",&n,&m,&PP);
for ( int i = 1; i <= n; ++i )
scanf("%d%d",&p[i].u,&p[i].v);
for ( int i = 1; i <= m; ++i )
{
scanf("%d%d%d%d",&p[i+n].u,&p[i+n].v,&p[i+n+m].u,&p[i+n+m].v);
wall[i].u = p[i+n].u; wall[i].v = p[i+n].v;
wall[i+m].u = p[i+n+m].u; wall[i+m].v=p[i+n+m].v;
}
for ( int i = 1; i <= n; ++i )
{
scanf("%d",&u); id[u] = i;
}
N = n + m + m;
double r = makemap(),l = 0.0,mid;
while ( (r-l) > eps )
{
mid = ( r + l ) / 2;
if ( can(mid) == 1 ) r = mid;
else l = mid;
}
printf("%.2lf\n",r);
}
return 0;
}
H -
Park Visit(HDU 4607)
先用两遍DFS求出直径ans,当k小于等于直径时,答案为k-1;否则答案为(k-ans)*2+ans-1
K -
Cards(HDU 4610)
16种卡片,2^16种情况
#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<algorithm>
#define maxn 5000020
#define N 5000010
#define mm 50
using namespace std;
int pp[maxn+10],ge[75536];
bool Isp[maxn];
int you[mm],dan[50];
int n,m,nn,cnt,K,ans;
struct pai
{
int x,z;
}pi[mm];
void Prim()
{
memset(Isp,0,sizeof(Isp));
cnt = 0;
Isp[1] = 1;
for ( int i = 2; i < N; ++i )
if ( !Isp[i] )
for ( int j = 2; j * i < N; ++j )
Isp[i*j] = 1;
for ( int i = 2; i < N; ++i )
if ( !Isp[i] )
pp[++cnt] = i;
}
bool conditions1( int x )
{
if( !Isp[x] ) return 1;
else return 0;
}
bool conditions2( int x )
{
int gg =1,hh = 0;
for ( int i = 1; pp[i] * pp[i] <= x ; ++i )
{
if ( x % pp[i] == 0 )
{
hh = 0;
while ( x % pp[i] == 0 )
{
++hh;
x /= pp[i];
}
gg *= ( hh + 1 );
}
}
if ( x != 1 ) gg *= 2;
if ( !Isp[gg] ) return 1;
else return 0;
}
bool conditions3( int x )
{
int gg = 1, hh = 0,nn;
for ( int i = 1; pp[i] * pp[i] <= x; ++i )
{
if ( x % pp[i] == 0 )
{
hh = pp[i];
nn = 1;
while ( x % pp[i] == 0 )
{
nn += hh;
hh *= pp[i];
x /= pp[i];
}
gg *= nn;
}
}
if( x != 1 ) gg *= ( x+ 1 );
if ( !Isp[gg] ) return 1;
else return 0;
}
bool conditions4( int x )
{
if( x == 1 )
return 1;
int yz[40], cn=-1;
bool flag;
for( int i = 1; pp[i] * pp[i] <= x; i++ )
{
if( x % pp[i] == 0 )
{
int nn = 0;
while( x % pp[i] == 0 )
{
x /= pp[i];
nn++;
}
yz[++cn] = nn;
}
}
if( x != 1 ) yz[++cn] = 1;
for( int i = 0; i <= cn; i++ )
{
if( yz[i] % 4 == 1 || yz[i] % 4 == 2 )
{
flag = 0;
for( int j = 0; j <= cn; j++ )
{
if( j != i && yz[j] % 2 == 1 )
flag = 1;
}
if( flag == 0 )
return 0;
}
}
return 1;
}
int cmp( pai p1, pai p2 )
{
return p1.z > p2.z;
}
int main()
{
int T;
Prim();
for ( int i = 0; i < 16; ++i )
{
pi[i].x = i;
pi[i].z = 0;
for ( int j = 0; j < 4; ++j )
if ( i & (1<<j) ) pi[i].z++;
you[i] = pi[i].z;
}
sort(pi,pi+16,cmp);
scanf("%d",&T);
while ( T-- )
{
scanf("%d%d",&n,&K);
memset(ge,0,sizeof(ge));
int now = 0,a = 0, y = 0, x = 0,z = 0;
for ( int i = 1; i <= n; ++i )
{
scanf("%d%d",&x,&z);
a = 0; y = 0;
if ( conditions1(x) ) y |= 1;
if ( conditions2(x) ) y |= 2;
if ( conditions3(x) ) y |= 4;
if ( conditions4(x) ) y |= 8;
for ( int j = 0; j < 4; ++j )
if ( y & 1 << j ) ++a;
if ( i == n ) printf("%d\n",a);
else printf("%d ",a);
ge[y] += z;
}
for ( int i = 0; i < 4 ; ++i )
scanf("%d",&dan[i]);
for ( int i = 0; i < 16; ++i )
if ( ge[i] != 0 ) now |= 1<<i;
ans = -1e9;
for ( int i = 0; i < ( 1 << 16 ); ++i )
{
int num = 0,res= 0, zhang = 0,gg;
if ( i == ( i & now) )
{
for ( int j = 0; j < 16; ++j )
if ( i & (1<<j) )
{ ++num;
9dcc
res += you[j]; zhang = zhang | j; }
if ( num > K ) continue;
for ( int j = 0; j < 16; ++j )
if ( i & ( 1 << pi[j].x ) )
{
gg = ge[pi[j].x];
--gg;
gg = min(gg,K-num);
num += gg;
res += you[pi[j].x] * gg;
}
if ( num != K ) continue;
for ( int j = 0; j <= 3 ; ++j )
if ( ( zhang & ( 1 << j ) )== 0 ) res += dan[j];
ans = max(ans,res);
}
}
printf("%d\n",ans);
}
return 0;
}
A - Harvest Moon(HDU4600)
题意:给你好多种种子,每种都有价格和收益。再给你一片地,问你只选一种种子播种的最大收益。
思路:枚举每种种子然后模拟。我很煞笔的开了个数组记录大小为i的土地的数量。TLE到死,最后很猥琐的除GCD,950ms水过。
#include<stdio.h> #include<string.h> #include<stdlib.h> #define maxn 1100 #define maxm 11 #define Clear(a,b) memset(a,b,sizeof(a)) #define LL __int64 int gcd(int a,int b) { if (b == 0) return a; else return gcd(b,a%b); } inline LL Max(LL a,LL b) { if (a > b) return a; return b; } inline LL Min(LL a,LL b) { if (a > b) return b; return a; } short int rec[maxn][maxm] = {0}; void cal_grid(int w,int h,int g[maxm]) { int w3,h3; g[9] = (w / 3) * (h / 3); w3 = w % 3; h3 = h % 3; g[3 * w3 + 3 * h3 - w3 * h3]++; g[w3 * 3] += ((h - 3) / 3); g[h3 * 3] += ((w - 3) / 3); g[w3 * h3] += 2; return ; } LL cal_get(int day,int mon,int q,int p,int n,int m,int g[maxm]) { int i,j,rest,num; LL money = mon; //day--; //printf("day:%d\n",day); //for(i = 1;i <= 9;i++) printf("%d ",g[i]);printf("\n"); //printf("%d %d %d %d",q,p,n,m); if (m == 0) { day /= n; n /= n; for(i = 0;i <= day;i++){ if (i >= 1) for(j = 1;j <= 9;j++) if (rec[i][j] > 0){ money += rec[i][j] * j * p; g[j] += rec[i][j]; rec[i][j] = 0; } for(j = 9;j >= 1;j--) if (g[j] >= 0 && i + n <= day && j * p > q){ num = Min(money / q,g[j]); money -= num * q; g[j] -= num; rec[i+1][j] += num; } } } else { //printf("\n%dxxx%d\n",i,day); int GCD = gcd(n,m); day /= GCD; n /= GCD; m /= GCD; for(i = 0;i <= day;i++){ rest = day - i; for(j = 9;j >= 1;j--) if (rec[i][j] > 0) { money += rec[i][j] * j * p; if (i + m <= day) rec[i+m][j] += rec[i][j]; rec[i][j] = 0; } //printf("%dxxx%d\n",i,day); for(j = 9;j >= 1;j--) if (g[j] > 0) { num = Min(money / q,g[j]); //sb了 if (rest >= n && (((rest - n) / m) * p + p) * j > q) { money -= num * q; rec[i+n][j] += num; g[j] -= num; } } } } //printf("OK\n"); return money; } int Work() { int Y,i,j,h,w,A,D,q,p,n,m; LL ans = 0; int grid[maxm] = {0},grid2[maxm] = {0}; scanf("%d%d%d%d%d",&w,&h,&A,&D,&Y); cal_grid(h,w,grid); //for(i = 1;i <= 9;i++) printf("%d ",grid[i]);printf("\n"); for(i = 1;i <= A;i++) { scanf("%d%d%d%d",&q,&p,&n,&m); for(j = 0;j < 10;j++) grid2[j] = grid[j]; ans = Max(ans,cal_get(D,Y,q,p,n,m,grid2)); } printf("%I64d\n",ans); //大傻逼 return 0; } int main() { int Cas; //freopen("test.in","r",stdin); //freopen("test.out","w",stdout); scanf("%d",&Cas); while(Cas--) Work(); return 0; }
C - Partition(HDU 4602)
这题猥琐的算前几项然后搜的公式
#include<stdio.h> #include<iostream> #include<stdlib.h> #include<string> #include<string.h> #define LL _int64 const LL Mod = 1000000007; LL QPow(LL x,LL n) { if (n == 0) return 1; if (n == 1) return x; LL tmp = QPow(x,n>>1); if (n & 1) return (((tmp * tmp) % Mod) * x) % Mod; else return (tmp * tmp) % Mod; } LL Work() { LL n,k,dif; scanf("%I64d%I64d",&n,&k); dif = n - k; if (dif < 0) printf("0\n"); else if (dif == 0) printf("1\n"); else if (dif == 1) printf("2\n"); else printf("%I64d\n",(dif+3) * QPow(2,dif-2) % Mod); return 0; } int main() { int Cas; scanf("%d",&Cas); while(Cas--) Work(); return 0; }F - Magic Ball Game(HDU 4605)
题意:给你一颗树,想象一个小球从根往下落,问你小球从根到某点的概率。
思路:首先,将路径统计一下,分为左路径和右路径,然后分别统计有多少大于X的。统计我用的傻逼树。
//先分左右,离线保存,两颗傻逼树,DFS #include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> #include <set> #include <map> #include <vector> #include <queue> #include <ctime> #pragma comment(linker, "/STACK:32000000") using namespace std; #define LL long long #define Clear(a,b) memset(a,b,sizeof(a)) const int N = 300010; const int INF=0x7FFFFFFF; vector<int> O ; int X ,ansx ,ansy ,son [2],w ; struct SBT { int key,left,right,size; } Tree_L ,Tree_R ; int Root_L,Root_R,top; void left_rot(int &x,SBT tree[]) { int y = tree[x].right; tree[x].right = tree[y].left; tree[y].left = x; tree[y].size = tree[x].size;//转上去的节点数量为先前此处节点的size tree[x].size = tree[tree[x].left].size + tree[tree[x].right].size + 1; x = y; } void right_rot(int &x,SBT tree[]) { int y = tree[x].left; tree[x].left = tree[y].right; tree[y].right = x; tree[y].size = tree[x].size; tree[x].size = tree[tree[x].left].size + tree[tree[x].right].size + 1; x = y; } void maintain(int &x,bool flag,SBT tree[]) { if(flag == false)//左边 { if(tree[tree[tree[x].left].left].size > tree[tree[x].right].size)//左孩子的左子树大于右孩子 right_rot(x,tree); else if(tree[tree[tree[x].left].right].size > tree[tree[x].right].size)//右孩子的右子树大于右孩子 { left_rot(tree[x].left,tree); right_rot(x,tree); } else return; } else //右边 { if(tree[tree[tree[x].right].right].size > tree[tree[x].left].size)//右孩子的右子树大于左孩子 left_rot(x,tree); else if(tree[tree[tree[x].right].left].size > tree[tree[x].left].size)//右孩子的左子树大于左孩子 { right_rot(tree[x].right,tree); left_rot(x,tree); } else return; } maintain(tree[x].left,false,tree); maintain(tree[x].right,true,tree); maintain(x, 4000 true,tree); maintain(x,false,tree); } /* *insert没有合并相同的元素,如果出现相同的元素则把它放到右子树上,这样能保证求第k小数的时候对相同元素也能正确 */ bool find(int &x,int key,SBT tree[]) { if (x == 0) return 0; if (key == tree[x].key) return 1; if (key < tree[x].key) return find(tree[x].left,key,tree); else return find(tree[x].right,key,tree); } void insert(int &x,int key,SBT tree[]) { if(x == 0) { x = ++top; tree[x].left = tree[x].right = 0; tree[x].size = 1; tree[x].key = key; } else { tree[x].size ++; if(key < tree[x].key) insert(tree[x].left,key,tree); else insert(tree[x].right,key,tree);//相同元素插入到右子树中 maintain(x, key >= tree[x].key,tree);//每次插入把平衡操作压入栈中 } } int del(int &p,int w,SBT tree[]) { if (tree[p].key==w || (tree[p].left==0 && w<tree[p].key) || (tree[p].right==0 && w>tree[p].key)) { int delnum=tree[p].key; if (tree[p].left==0 || tree[p].right==0) p=tree[p].left+tree[p].right; else tree[p].key=del(tree[p].left,INF,tree); return delnum; } if (w<tree[p].key) return del(tree[p].left,w,tree); else return del(tree[p].right,w,tree); } int remove(int &x,int key,SBT tree[]) { int d_key; //if(!x) return 0; tree[x].size --; if((key == tree[x].key)||(key < tree[x].key && tree[x].left == 0) || (key>tree[x].key && tree[x].right == 0)) { d_key = tree[x].key; if(tree[x].left && tree[x].right) { tree[x].key = remove(tree[x].left,tree[x].key+1,tree); } else { x = tree[x].left + tree[x].right; } } else if(key > tree[x].key) d_key = remove(tree[x].right,key,tree); else if(key < tree[x].key) d_key = remove(tree[x].left,key,tree); return d_key; } int getmin(int root,SBT tree[]) { int x; for(x = root ; tree[x].left; x = tree[x].left); return tree[x].key; } int getmax(int root,SBT tree[]) { int x; for(x = root ; tree[x].right; x = tree[x].right); return tree[x].key; } int select(int &x,int k,SBT tree[])//求第k小数 { int r = tree[tree[x].left].size + 1; if(r == k) return tree[x].key; else if(r < k) return select(tree[x].right,k - r,tree); else return select(tree[x].left,k,tree); } int rank(int &x,int key,SBT tree[])//求key排第几 { if(key < tree[x].key) return rank(tree[x].left,key,tree); else if(key > tree[x].key) return rank(tree[x].right,key,tree) + tree[tree[x].left].size + 1; return tree[tree[x].left].size + 1; } int pred(int &x,int y,int key,SBT tree[])//前驱 小于 { if(x == 0) return y; if(tree[x].key < key) return pred(tree[x].right,x,key,tree); else return pred(tree[x].left,y,key,tree); } int succ(int &x,int y,int key,SBT tree[])//后继 大于 { if(x == 0) return y; if(tree[x].key > key) return succ(tree[x].left,x,key,tree); else return succ(tree[x].right,y,key,tree); } void inorder(int &x,SBT tree[]) { if(x==0) return; else { inorder(tree[x].left,tree); cout<<x<<" "<<tree[x].key<<" "<<" "<<tree[x].size<<" "<<tree[tree[x].left].key<<" "<<tree[tree[x].right].key<<endl; inorder(tree[x].right,tree); } } //模板 void dfs(int x,int Num_L,int Num_R) { //Cal int i,t1,t2; //printf("%d %d yy\n",x,O[x].size()); for(i = 0;i < O[x].size();i++){ int tmp = O[x][i]; //printf("fuck\n"); if (find(Root_L,X[tmp],Tree_L) || find(Root_R,X[tmp],Tree_R)) continue; //tot = Num_L + Num_R; //printf("fuck\n"); insert(Root_L,X[tmp],Tree_L); insert(Root_R,X[tmp],Tree_R); t1 = rank(Root_L,X[tmp],Tree_L); t2 = rank(Root_R,X[tmp],Tree_R); remove(Root_L,X[tmp],Tree_L); remove(Root_R,X[tmp],Tree_R); t1--;t2--; //printf("fuck %d %d %d %d\n",t1,t2,Num_L,Num_R); ansx[tmp] = t2; ansy[tmp] = t1 * 3 + (Num_L - t1) + t2 * 3 + (Num_R - t2); } //printf("L\n"); //L if (son[x][0] > 0) { insert(Root_L,w[x],Tree_L); dfs(son[x][0],Num_L+1,Num_R); remove(Root_L,w[x],Tree_L); } //printf("R\n"); //R if (son[x][1] > 0) { insert(Root_R,w[x],Tree_R); dfs(son[x][1],Num_L,Num_R+1); remove(Root_R,w[x],Tree_R); } return ; } void Work() { Root_L = Root_R = top = 0; int n,m,i,u,a,b; Clear(son,0); Clear(ansx,-1); Clear(ansy,-1); Clear(w,0); Clear(X,0); scanf("%d",&n); for(i = 1;i <= n;i++) O[i].clear(); for(i = 1;i <= n;i++) scanf("%d",&w[i]); scanf("%d",&m); for(i = 1;i <= m;i++) scanf("%d%d%d",&u,&a,&b), son[u][0] = a, son[u][1] = b; scanf("%d",&m); for(i = 1;i <= m;i++) scanf("%d%d",&u,&X[i]), O[u].push_back(i); //printf("xxxx\n"); dfs(1,0,0); //printf("xxxx\n"); for(i = 1;i <= m;i++) if (ansx[i] == -1) printf("0\n"); else printf("%d %d\n",ansx[i],ansy[i]); return ; } int main() { int cas; // freopen("test.in","r",stdin); // freopen("test.out","w",stdout); scanf("%d",&cas); while(cas--) Work(); return 0; }
G -
Occupy Cities(HDU 4606)
floyd+二分+最小路径覆盖
#include<iostream>
#include<string.h>
#include<stdio.h>
#include<string>
#include<math.h>
#define oo 1e9
#define eps 1e-8
#define maxn 500
#define maxm 10000
using namespace std;
struct Point
{
int u,v;
Point(){}
Point(double a,double b):u(a),v(b){}
Point operator - (const Point p) {return Point(u-p.u,v-p.v);}
}p[maxn],wall[maxn];
double ma[maxn][maxn];
int map[maxn][maxn],match[maxn],id[maxn];
bool vis[maxn];
int n,m,PP,T,N,M;
int dlcmp(double x) {return x<-eps?-1:x>eps;}
double sqr(double x) {return x*x;}
double dist(Point a,Point b) {return sqrt(sqr(a.u-b.u)+sqr(a.v-b.v));}
double cross(Point a,Point b) {return a.u*b.v-b.u*a.v;}
int segment_intersect(Point s1,Point e1,Point s2,Point e2)
{
if (max(s1.u,e1.u)>min(s2.u,e2.u)&&max(s2.u,e2.u)>min(s1.u,e1.u)&&max(s1.v,e1.v)>min(s2.v,e2.v)&&max(s2.v,e2.v)>min(s1.v,e1.v)&&
dlcmp(cross(e1-s1,s2-s1))*dlcmp(cross(e1-s1,e2-s1))<0&&dlcmp(cross(e2-s2,s1-s2))*dlcmp(cross(e2-s2,e1-s2))<0)
return 1;
else
return 0;
}
bool NO( int x, int y )
{
for ( int i = 1; i <= m; ++i )
{
if ( segment_intersect(p[x],p[y],wall[i],wall[i+m]) ) return 0;
}
return 1;
}
double makemap()
{
for ( int i = 1; i <= N; ++i )
for ( int j = 1; j <= N; ++j )
if ( i != j ) ma[i][j] = oo;
else ma[i][j] = 0;
for ( int i = 1; i <= N; ++i )
for ( int j = 1; j < i; ++j )
if ( NO(i,j) )
{
ma[i][j] = min(ma[i][j],dist(p[i],p[j]));
ma[j][i] = ma[i][j];
}
for ( int k = 1; k <= N; ++k )
for ( int i = 1; i <= N; ++i )
if ( k != i )
for ( int j = 1; j <= N; ++j )
if ( i !=j && k != j && ma[i][j] > ma[i][k] + ma[k][j] && ma[i][k] < oo && ma[k][j] < oo )
ma[i][j] = ma[i][k]+ma[k][j];
double maxx = 0;
for ( int i = 1; i <= n; ++i )
for ( int j = 1; j < i; ++j )
if ( maxx < ma[i][j] ) maxx = ma[i][j];
return maxx;
}
int find( int x )
{
for ( int i = 1; i <= n; ++i )
if ( map[x][i] == 1 && vis[i] == 0 )
{
vis[i] = 1;
if ( match[i] == 0 || find(match[i]) )
{
match[i] = x;
return 1;
}
}
return 0;
}
bool can( double mid )
{
memset(map,0,sizeof(map));
for ( int i = 1; i <= n; ++i )
for ( int j = 1; j <= n; ++j )
if ( id[i] < id[j] &&ma[i][j]-mid <=0 )
map[i][j] = 1;
memset(match,0,sizeof(match));
int res = 0;
for ( int i = 1; i <= n; ++i )
{
memset(vis,0,sizeof(vis));
res += find(i);
}
if ( n - res <= PP ) return 1;
else return 0;
}
int main()
{
int u;
scanf("%d",&T);
while ( T-- )
{
scanf("%d%d%d",&n,&m,&PP);
for ( int i = 1; i <= n; ++i )
scanf("%d%d",&p[i].u,&p[i].v);
for ( int i = 1; i <= m; ++i )
{
scanf("%d%d%d%d",&p[i+n].u,&p[i+n].v,&p[i+n+m].u,&p[i+n+m].v);
wall[i].u = p[i+n].u; wall[i].v = p[i+n].v;
wall[i+m].u = p[i+n+m].u; wall[i+m].v=p[i+n+m].v;
}
for ( int i = 1; i <= n; ++i )
{
scanf("%d",&u); id[u] = i;
}
N = n + m + m;
double r = makemap(),l = 0.0,mid;
while ( (r-l) > eps )
{
mid = ( r + l ) / 2;
if ( can(mid) == 1 ) r = mid;
else l = mid;
}
printf("%.2lf\n",r);
}
return 0;
}
H -
Park Visit(HDU 4607)
先用两遍DFS求出直径ans,当k小于等于直径时,答案为k-1;否则答案为(k-ans)*2+ans-1
#include<iostream> #include<string.h> #include<string> #include<stdio.h> #define maxn 200000 #define maxm 500000 using namespace std; int first[maxn],cnt,dep[maxn]; struct edd { int v,next; }e[maxm]; void add( int u, int v ) { e[cnt].v = v; e[cnt].next = first[u]; first[u] = cnt++; } void dfs(int u, int fa, int deep ) { dep[u] = deep; for ( int i = first[u]; i != -1; i = e[i].next ) { int v = e[i].v; if ( v != fa ) dfs(v,u,deep+1); } } int main() { int T,n,m,u,v; scanf("%d",&T); while ( T-- ) { scanf("%d%d",&n,&m); memset(first,-1,sizeof(first)); cnt = 0; for ( int i = 1; i < n; ++i ) { scanf("%d%d",&u,&v); add(u,v); add(v,u); } memset(dep,0,sizeof(dep)); int res = 1; dfs(res,0,0); for ( int i = 2; i <= n; ++i ) if ( dep[i] > dep[res] ) res = i; dfs(res,0,0); int ans = 0,k; for ( int i = 1; i <= n; ++i ) if ( ans < dep[i] ) ans = dep[i]; ans++; for ( int i = 1; i <= m; ++i ) { scanf("%d",&k); if ( k <= ans ) printf("%d\n",k-1); else printf("%d\n",(k-ans)*2+ans-1); } } return 0; }
K -
Cards(HDU 4610)
16种卡片,2^16种情况
#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<algorithm>
#define maxn 5000020
#define N 5000010
#define mm 50
using namespace std;
int pp[maxn+10],ge[75536];
bool Isp[maxn];
int you[mm],dan[50];
int n,m,nn,cnt,K,ans;
struct pai
{
int x,z;
}pi[mm];
void Prim()
{
memset(Isp,0,sizeof(Isp));
cnt = 0;
Isp[1] = 1;
for ( int i = 2; i < N; ++i )
if ( !Isp[i] )
for ( int j = 2; j * i < N; ++j )
Isp[i*j] = 1;
for ( int i = 2; i < N; ++i )
if ( !Isp[i] )
pp[++cnt] = i;
}
bool conditions1( int x )
{
if( !Isp[x] ) return 1;
else return 0;
}
bool conditions2( int x )
{
int gg =1,hh = 0;
for ( int i = 1; pp[i] * pp[i] <= x ; ++i )
{
if ( x % pp[i] == 0 )
{
hh = 0;
while ( x % pp[i] == 0 )
{
++hh;
x /= pp[i];
}
gg *= ( hh + 1 );
}
}
if ( x != 1 ) gg *= 2;
if ( !Isp[gg] ) return 1;
else return 0;
}
bool conditions3( int x )
{
int gg = 1, hh = 0,nn;
for ( int i = 1; pp[i] * pp[i] <= x; ++i )
{
if ( x % pp[i] == 0 )
{
hh = pp[i];
nn = 1;
while ( x % pp[i] == 0 )
{
nn += hh;
hh *= pp[i];
x /= pp[i];
}
gg *= nn;
}
}
if( x != 1 ) gg *= ( x+ 1 );
if ( !Isp[gg] ) return 1;
else return 0;
}
bool conditions4( int x )
{
if( x == 1 )
return 1;
int yz[40], cn=-1;
bool flag;
for( int i = 1; pp[i] * pp[i] <= x; i++ )
{
if( x % pp[i] == 0 )
{
int nn = 0;
while( x % pp[i] == 0 )
{
x /= pp[i];
nn++;
}
yz[++cn] = nn;
}
}
if( x != 1 ) yz[++cn] = 1;
for( int i = 0; i <= cn; i++ )
{
if( yz[i] % 4 == 1 || yz[i] % 4 == 2 )
{
flag = 0;
for( int j = 0; j <= cn; j++ )
{
if( j != i && yz[j] % 2 == 1 )
flag = 1;
}
if( flag == 0 )
return 0;
}
}
return 1;
}
int cmp( pai p1, pai p2 )
{
return p1.z > p2.z;
}
int main()
{
int T;
Prim();
for ( int i = 0; i < 16; ++i )
{
pi[i].x = i;
pi[i].z = 0;
for ( int j = 0; j < 4; ++j )
if ( i & (1<<j) ) pi[i].z++;
you[i] = pi[i].z;
}
sort(pi,pi+16,cmp);
scanf("%d",&T);
while ( T-- )
{
scanf("%d%d",&n,&K);
memset(ge,0,sizeof(ge));
int now = 0,a = 0, y = 0, x = 0,z = 0;
for ( int i = 1; i <= n; ++i )
{
scanf("%d%d",&x,&z);
a = 0; y = 0;
if ( conditions1(x) ) y |= 1;
if ( conditions2(x) ) y |= 2;
if ( conditions3(x) ) y |= 4;
if ( conditions4(x) ) y |= 8;
for ( int j = 0; j < 4; ++j )
if ( y & 1 << j ) ++a;
if ( i == n ) printf("%d\n",a);
else printf("%d ",a);
ge[y] += z;
}
for ( int i = 0; i < 4 ; ++i )
scanf("%d",&dan[i]);
for ( int i = 0; i < 16; ++i )
if ( ge[i] != 0 ) now |= 1<<i;
ans = -1e9;
for ( int i = 0; i < ( 1 << 16 ); ++i )
{
int num = 0,res= 0, zhang = 0,gg;
if ( i == ( i & now) )
{
for ( int j = 0; j < 16; ++j )
if ( i & (1<<j) )
{ ++num;
9dcc
res += you[j]; zhang = zhang | j; }
if ( num > K ) continue;
for ( int j = 0; j < 16; ++j )
if ( i & ( 1 << pi[j].x ) )
{
gg = ge[pi[j].x];
--gg;
gg = min(gg,K-num);
num += gg;
res += you[pi[j].x] * gg;
}
if ( num != K ) continue;
for ( int j = 0; j <= 3 ; ++j )
if ( ( zhang & ( 1 << j ) )== 0 ) res += dan[j];
ans = max(ans,res);
}
}
printf("%d\n",ans);
}
return 0;
}
相关文章推荐
- 2013 Multi-University Training Contest 1 Occupy Cities HDU 4606
- 2013 Multi-University Training Contest 4 Who's Aunt Zhang
- 2013 Multi-University Training Contest 8
- hdu 4619 匈牙利算法 求最大匹配 2013 Multi-University Training Contest 2
- Integer Partition(hdu4658)2013 Multi-University Training Contest 6 整数拆分二
- 2013 Multi-University Training Contest 1 I-number 大数
- 2013 Multi-University Training Contest 1 Warm up HDU 4612
- 2013 Multi-University Training Contest 5
- [置顶] 2013 Multi-University Training Contest 8
- 2013 Multi-University Training Contest 10 解题报告(更新中)
- 2013 Multi-University Training Contest 1 Partition
- 2013 Multi-University Training Contest 9
- 2013 Multi-University Training Contest 10
- 2013 Multi-University Training Contest 10
- HDU 4609 3-idiots(FFT优化 + 计数方法)——2013 Multi-University Training Contest 1
- 2013 Multi-University Training Contest 1 I-number
- 2013 Multi-University Training Contest 1 Vases and Flowers HDU 4614
- 2013 Multi-University Training Contest 1——I-number
- 2013 Multi-University Training Contest 7 解题报告(更新中)
- HDU 4609 3-idiots(FFT优化 + 计数方法)——2013 Multi-University Training Contest 1