2017ACM/ICPC亚洲区沈阳站

大力施工中...(9/13)

 

A.BBP Formula(hdu6217)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6217

 

开始不太会啊?后来看了看dalao的博客,发现,这个给的公式很奇妙啊,计算第n位小数,首先将式子乘上16^(n-1),然后计算小数部分就行了,因为我们只考虑小数部分,所以可以在计算的过程中,将分子对分母取模,所得到的小数部分是相同的,然后将小数部分乘16就可以得到16进制下的取值了。而且看起来精度没有什么问题。

 

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll qpow(ll a,ll b,ll MOD)
{
	ll ret=1;
	while(b)
	{
		if(b&1)
			ret=ret*a%MOD;
		a=a*a%MOD;
		b>>=1;
	}
	return ret;
}
double BBP(int n,double a,double b)
{
	double ret=0;
	for(int k=0;k<=n;k++)
	{
		ret+=qpow(16,n-k,8*k+b)*1.0/(k*8.0+b);
	}
	return ret*a;
}
double cal(int n)
{
	return BBP(n,4,1)+BBP(n,-2,4)+BBP(n,-1,5)+BBP(n,-1,6);
}
int main()
{
	//freopen("in.txt","r",stdin);
	//freopen("out.txt","w",stdout);
	int T;
	scanf("%d",&T);
	for(int _=1;_<=T;_++)
	{
		int n;
		scanf("%d",&n);
		n--;
		double r=cal(n);
		r=r-(ll)r;
		if(r<0)
			r+=1.0;
		r*=16;
		int res=r;
		printf("Case #%d: %d %c\n",_,n+1,res>9?res-10+'A':res+'0');
	}
	return 0;
}

 

C.Empty Convex Polygons(hdu6219)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6219

 

最大空凸包板题,首先枚举一个点作为凸包的最下的点,然后进行极角排序,dp[i][j]表示最后一条边是点i到j缩围成的最大空凸包的面积是多少,进行转移即可,每次都要判断,是否有点在凸包内,转移时要判断两条线的夹角关系,时间复杂度O(n^4),好象有n^3的做法啊?有空学一学。

 

代码:

#include<bits/stdc++.h>
using namespace std;
const int MAXN=55;
const double eps=1e-6;
int dp[MAXN][MAXN];
int n;
struct Point
{
	int x,y,dis;
	double angel;
	double operator ^ (const Point &b)const//叉积
	{
		return x*b.y-y*b.x;
	}
	bool operator == (const Point &b)const
	{
		return x==b.x&&y==b.y;
	}
	Point operator - (const Point &b)const
	{
		Point ret;
		ret.x=x-b.x;
		ret.y=y-b.y;
		return ret;
	}
}p[MAXN],st[MAXN],p0;
int sgn(double x) 
{
	if(fabs(x)<eps)
		return 0;
	if(x<0)
		return -1;
	else
		return 1;
}
int area(Point a,Point b)
{
	return abs(a^b);
}
int dis(const Point a,const Point b)
{
	return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}
bool cmp(const Point p1,const Point p2)
{
	if(sgn(p1.angel-p2.angel)==0)
		return p1.dis<p2.dis;
	return p1.angel<p2.angel;
}
int judge(Point P,Point a,Point b,Point c)
{
	Point A,B;
	int res[3];
	A=P-a;B=b-a;res[0]=A^B;
	A=b-c;B=P-c;res[1]=A^B;
	A=P-c;B=a-c;res[2]=A^B;
	if(res[0]>0&&res[1]>=0&&res[2]>0)
	{
		if(res[1]==0)
		{
			int dis1=dis(b,c);
			int dis2=dis(P,c);
			if(dis1>dis2)
				return 1;
		}
		return 2;
	}
	return 0;
}
int getans()
{
	int s,ret=0;
	sort(st+1,st+1+n,cmp);
	for(int i=1;i<=n;i++)
	{
		if(st[i]==p0)
		{
			s=i;
			break;
		}
	}
	memset(dp,-1,sizeof(dp));
	for(int i=s+1;i<=n;i++)
	{
		dp[s][i]=0;
	}
	for(int i=s+1;i<=n;i++)
	{
		for(int j=i+1;j<=n;j++)
		{
			//dp[i][j],最后一条线是(i,j)
			int flag=0;
			for(int k=1;k<=n;k++)
			{
				int f=judge(st[k],st[j],st[i],st[s]);
				flag=max(flag,f);
			}
			if(flag==1)
				dp[i][j]=max(dp[i][j],dp[s][i]+area(st[i]-st[s],st[j]-st[s]));
			if(flag)
				continue;
			Point now=st[j]-st[i];
			for(int k=1;k<=n;k++)
			{
				if(dp[k][i]!=-1)
				{
					Point tmp=st[i]-st[k];
					int res=tmp^now;
					if(res>=0)
						dp[i][j]=max(dp[i][j],dp[k][i]+area(st[i]-st[s],st[j]-st[s]));
				}
			}
			ret=max(ret,dp[i][j]);
		}
	}
	return ret;
}
void solve()
{
	int ans=0;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d%d",&p[i].x,&p[i].y);
	}
	for(int i=1;i<=n;i++)
	{
		p0=p[i];
		for(int j=1;j<=n;j++)
		{
			st[j]=p[j];
			st[j].angel=atan2(st[j].y-p0.y,st[j].x-p0.x);
			st[j].dis=dis(st[j],p0);
		}
		ans=max(ans,getans());
	}
	printf("%d",ans>>1);
	printf(".%d\n",(ans&1)*5);
}
int main()
{
	//freopen("in.txt","r",stdin);
	//freopen("out.txt","w",stdout);
	int T;
	scanf("%d",&T);
	while(T--)
	{
		solve();
	}
	return 0;
}

 

F.Heron and His Triangle(hdu6222)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6222

 

打个表找规律,发现dp[i]=4*dp[i-1]-dp[i-2],dp[0]=2,dp[1]=4,然后java大数就好了。

 

代码:

import java.math.*;
import java.util.*;
import java.io.*;
public class Main 
{
	static public Vector init()
	{
		BigInteger a,b,c,lim,four;
		a=new BigInteger("2");
		b=new BigInteger("4");
		four=new BigInteger("4");
		lim=new BigInteger("1000000000000000000000000000000");
		Vector v=new Vector();
		c=b.multiply(four).subtract(a);
		v.add(b);
		v.add(c);
		while(c.compareTo(lim)<=0)
		{
			a=b;
			b=c;
			c=b.multiply(four).subtract(a);
			v.add(c);
		}
		return v;
	}
	public static void main(String[] args) 
	{
		// TODO Auto-generated method stub
		Scanner cin=new Scanner(new BufferedInputStream(System.in));
		Vector v=init();
		int T=cin.nextInt();
		while(T>0)
		{
			T--;
			BigInteger x=cin.nextBigInteger();
			for(int i=0;i<v.size();i++)
			{
				if(x.compareTo((BigInteger)v.get(i))<=0)
				{
					System.out.println(v.get(i));
					break;
				}
			}
		}
	}

}

 

G.Infinite Fraction Path(hdu6223)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6223

 

我好像是个辣鸡啊???

排序排反了debug了一个小时???

这个题怎么爆爆爆就过了啊????

直接按层搜索,随便剪剪就行了

 

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN=150000+5;
int nxt[MAXN],a[MAXN],ans[MAXN],vis[MAXN],mx;
char s[MAXN];
struct node
{
    int val,dp;
    node(int _val=0,int _dp=0):val(_val),dp(_dp){}
    bool operator<(const node &o)const
    {
        if(dp==o.dp)
            return a[val]<a[o.val];
        return dp>o.dp;
    }
};
void init(int _n)
{
    mx=0;
    for(int i=0;i<_n;i++)
    {
        nxt[i]=(1LL*i*i+1LL)%(ll)_n;
        a[i]=s[i]-'0';
        mx=max(a[i],mx);
        ans[i]=0;vis[i]=-1;
    }
}
void bfs(int n)
{
    priority_queue<node> Q;
    ans[0]=mx;
    for(int i=0;i<n;i++)
    {
        if(a[i]==mx)
            Q.push(node(i,0));
    }
    while(!Q.empty())
    {
        node top=Q.top();
        Q.pop();
        int val,dp;
        val=top.val;dp=top.dp;
        if(a[val]<ans[dp])
            continue;
        node nx=node(nxt[val],dp+1);
        if(vis[nx.val]<nx.dp)
			vis[nx.val]=nx.dp;
		else
			continue;
		if(nx.dp<n&&a[nx.val]>=ans[nx.dp])
        {
            ans[nx.dp]=a[nx.val];
            Q.push(nx);
        }
    }
    for(int i=0;i<n;i++)
    {
        printf("%d",ans[i]);
    }
    printf("\n");
}
void solve()
{
    int n;
    scanf("%d",&n);
    scanf("%s",s);
    init(n);
    bfs(n);
}
int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int T;
    scanf("%d",&T);
    for(int _=1;_<=T;_++)
    {
        printf("Case #%d: ",_);
        solve();
    }
    return 0;
}

H.Legends of the Three Kingdoms(hdu6224)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6224

 

直接搜索就行,照着叉姐的代码写的

 

代码:

#include<bits/stdc++.h>
#define xx first
#define yy second
#define mp make_pair
#define pb push_back
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef tuple<double,double,double> State;
const double eps=1e-12;
inline int dcmp(double x)
{
	return x<-eps?-1:x>eps;
}
State dp[40][40][40][40][4];
template<int at>
State combine(vector<State> &vec)
{
	if(vec.empty()) return State(0,0,0);
	double mx=-1;
	for(const State &s:vec)
	{
		mx=max(mx,get<at>(s));
	}
	int cnt=0;
	State ret;
	for(const State &s:vec)
	{
		if(dcmp(get<at>(s)-mx)==0)
		{
			ret=State(get<0>(ret)+get<0>(s),
					  get<1>(ret)+get<1>(s),
					  get<2>(ret)+get<2>(s));
			cnt++;
		}
	}
	assert(cnt>0);
	return State(get<0>(ret)/cnt,
				 get<1>(ret)/cnt,
				 get<2>(ret)/cnt);
}
void init()
{
	for(int A=0;A<40;A++)
	{
		for(int B=0;B<40;B++)
		{
			for(int C=0;C<40;C++)
			{
				for(int D=0;D<40;D++)
				{
					for(int at=0,count=0;count<4;count++,at=(at+3)%4)
					{
						if(A==0)
						{
							if(B==0&&C==0&&D!=0)
							{
								dp[A][B][C][D][at]=State(0,0,1);
							}
							else
							{
								dp[A][B][C][D][at]=State(0,1,0);
							}
							continue;
						}
						if(B==0&&D==0)
						{
							dp[A][B][C][D][at]=State(1,0,0);
							continue;
						}
						if((A==0&&at==0)||
						   (B==0&&at==1)||
						   (C==0&&at==2)||
						   (D==0&&at==3))
						{
							dp[A][B][C][D][at]=dp[A][B][C][D][(at+1)%4];
							continue;
						}
						vector<State> vec;
						if(at==0||at==2)
						{
							if(B) vec.emplace_back(dp[A][B-1][C][D][at+1]);
							if(D) vec.emplace_back(dp[A][B][C][D-1][at+1]);
							dp[A][B][C][D][at]=combine<0>(vec);
						}
						else if(at==1)
						{
							if(A) vec.emplace_back(dp[A-1][B][C][D][at+1]);
							if(C) vec.emplace_back(dp[A][B][C-1][D][at+1]);
							if(D) vec.emplace_back(dp[A][B][C][D-1][at+1]);
							dp[A][B][C][D][at]=combine<1>(vec);
						}
						else if(at==3)
						{
							if(A) vec.emplace_back(dp[A-1][B][C][D][0]);
							if(B) vec.emplace_back(dp[A][B-1][C][D][0]);
							if(C) vec.emplace_back(dp[A][B][C-1][D][0]);
							dp[A][B][C][D][at]=combine<2>(vec);
						}
					}
				}
			}
		}
	}
}
int main()
{
	//freopen("in.txt","r",stdin);
	//freopen("out.txt","w",stdout);
	int T;
	init();
	scanf("%d",&T);
	while(T--)
	{
		int a,b,c,d;
		scanf("%d%d%d%d",&a,&c,&b,&d);
		const State &res=dp[a][b][c][d][0];
		printf("%.6lf %.6lf %.6lf\n",
				get<0>(res),
				get<1>(res),
				get<2>(res));
	}
	return 0;
}

I.Little Boxes(hdu6225)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6225

 

水题,直接上__int128就好了

 

代码:

#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;
void print(__int128 x)
{
	if(!x)
	{
		puts("0");
		return ;
	}
	string ret="";
	while(x)
	{
		ret+=x%10+'0';
		x/=10;
	}
	reverse(ret.begin(),ret.end());
	cout<<ret<<endl;
}
void solve()
{
	ll a,b,c,d;
	__int128 ans=0;
	scanf("%lld%lld%lld%lld",&a,&b,&c,&d);
	ans+=a;ans+=b;ans+=c;ans+=d;
	print(ans);
}

int main()
{
	//freopen("in.txt","r",stdin);
	//freopen("out.txt","w",stdout);
	int T;
	scanf("%d",&T);
	while(T--)
	{
		solve();
	}
	return 0;
}

 

K.Rabbits(hdu6227)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6227

 

签到题,从直接模拟第1个向第n个跳,或者第n个向第1个跳这两种情况,然后取最大值即可

 

代码:

#include<bits/stdc++.h>
using namespace std;
const int MAXN=505;
int a[MAXN];
void solve()
{
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
	}
	int ans=0,mx;
	mx=0;
	for(int i=2;i<n;i++)
	{
		mx+=a[i+1]-a[i]-1;
	}
	ans=max(ans,mx);
	mx=0;
	for(int i=1;i<n-1;i++)
	{
		mx+=a[i+1]-a[i]-1;
	}
	ans=max(ans,mx);
	printf("%d\n",ans);
}
int main()
{
	//freopen("in.txt","r",stdin);
	//freopen("out.txt","w",stdout);
	int T;
	scanf("%d",&T);
	while(T--)
	{
		solve();
	}
	return 0;
}

 

L.Tree(hdu6228)

 

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6228

 

对于每一条边,只要两边同时有k个以上的点就行,随便找一个度为1的点为根,然后dfs子树内外的点数就好了

 

代码:

#include<bits/stdc++.h>
using namespace std;
const int MAXN=2e5+5;
int sz[MAXN],head[MAXN],tot,root,ans,n,k;
struct edge
{
	int to,nxt;
}E[MAXN*2];
void addedge(int u,int v)
{
	E[tot].to=v;E[tot].nxt=head[u];head[u]=tot++;
	E[tot].to=u;E[tot].nxt=head[v];head[v]=tot++;
}
void init(int _n)
{
	tot=0;root=0;ans=0;
	for(int i=1;i<=_n;i++)
	{
		head[i]=-1;
		sz[i]=0;
	}
}
void dfsroot(int now,int fa)
{
	bool flag=false;
	for(int i=head[now];~i;i=E[i].nxt)
	{
		int v=E[i].to;
		if(v==fa)
			continue;
		flag=true;
		dfsroot(v,now);
	}
	if(!flag)
		root=now;
}
void dfssz(int now,int fa)
{
	sz[now]=1;
	for(int i=head[now];~i;i=E[i].nxt)
	{
		int v=E[i].to;
		if(v==fa)
			continue;
		dfssz(v,now);
		sz[now]+=sz[v];
	}
}
void dfsans(int now,int fa)
{
	if(n-sz[now]>=k&&sz[now]>=k)
		ans++;
	for(int i=head[now];~i;i=E[i].nxt)
	{
		int v=E[i].to;
		if(v==fa)
			continue;
		dfsans(v,now);
	}
}
void solve()
{
	scanf("%d%d",&n,&k);
	init(n);
	for(int i=1;i<n;i++)
	{
		int u,v;
		scanf("%d%d",&u,&v);
		addedge(u,v);
	}
	dfsroot(1,0);
	dfssz(root,0);
	dfsans(root,0);
	printf("%d\n",ans);
}
int main()
{
	//freopen("in.txt","r",stdin);
	//freopen("out.txt","w",stdout);
	int T;
	scanf("%d",&T);
	while(T--)
	{
		solve();
	}
	return 0;
}

 

M.Wandering Robots(hdu6229)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6229

 

wa,又是找规律题,最后发现,等于右下部分的所有的度的和比整张图的度的和,因为题目保证一定联通,所以,直接开一个map标记某个点有没有障碍,一个障碍一个障碍加进去即可。

 

代码:

#include<bits/stdc++.h>
#define mp make_pair
#define xx first
#define yy second
using namespace std;
typedef pair<int,int> pii;
map<pii,int> sv;
int tot,up,n,m;
int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
bool exist(int x,int y)
{
	if(x<0||x>n-1||y<0||y>n-1)
		return true;
	if(sv.find(mp(x,y))!=sv.end())
		return true;
	return false;
}
int getin(int x,int y)
{
	int ret=5;
	for(int i=0;i<4;i++)
	{
		int tx=x+dir[i][0];
		int ty=y+dir[i][1];
		if(exist(tx,ty))
			ret--;
	}
	return ret;
}
void handle(int x,int y)
{
	int sub=getin(x,y);
	tot-=sub;
	if(x+y>=n-1)
		up-=sub;
	for(int i=0;i<4;i++)
	{
		int tx=x+dir[i][0];
		int ty=y+dir[i][1];
		if(!exist(tx,ty))
		{
			tot--;
			if(tx+ty>=n-1)
				up--;
		}
	}
	sv[mp(x,y)]=1;
}
void solve()
{
	sv.clear();
	scanf("%d%d",&n,&m);
	tot=n*n*5-n*4;
	up=5*n*(n+1)/2-n*2-2;
	for(int i=1;i<=m;i++)
	{
		int x,y;
		scanf("%d%d",&x,&y);
		handle(x,y);
	}
	int g=__gcd(up,tot);
	up/=g;tot/=g;
	printf("%d/%d\n",up,tot);
}
int main()
{
	//freopen("in.txt","r",stdin);
	//freopen("out.txt","w",stdout);
	int T;
	scanf("%d",&T);
	for(int _=1;_<=T;_++)
	{
		printf("Case #%d: ",_);
		solve();
	}
	return 0;
}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值