您的位置:首页 > 大数据 > 人工智能

2013 Multi-University Training Contest 1

2013-07-27 02:05 399 查看
这场比赛。。。伤心了

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ACM