noip66

T1

前缀和优化+背包。

两班都做一遍,最后相同体积合并即可。

T2

考场想法:没啥好说的,因为是暴力。

然而读错题了,20pts也没了。。。

题目里的每种情况指的是集合点不同,让求的是,对于每一个集合点,求出其最小代价,并给所有点的最小代价求个总和。

正解:

image

Code
#include<cstdio>
#include<cctype>
#define MAX 1000003
#define re register
#define int long long
const int mod = 1e9+7;
namespace some
{
	struct stream
	{
		template<typename type>inline stream &operator >>(type &s)
		{
			bool w=0; s=0; char ch=getchar();
			while(!isdigit(ch)){ w|=ch=='-'; ch=getchar(); }
			while(isdigit(ch)){ s=(s<<1)+(s<<3)+(ch^48); ch=getchar(); }
			return s=w?-s:s,*this;
		}
	}cin;
	int n,m;
	struct graph
	{
		int next;
		int to;
	}edge[MAX<<1];
	int cnt=1,head[MAX];
	auto add = [](int u,int v) -> void { edge[++cnt] = (graph){head[u],v},head[u] = cnt; };
	auto fd = [](int &a,int b) { a = b-mod+a>=0?a+b-mod:a+b; };
}using namespace some;
namespace OMA
{
	int fac[MAX],inv[MAX];
	auto quickpow = [](int a,int b,int res = 1) -> int
	{
		while(b)
		{
			if(b&1)
			{ res = res*a%mod; }
			a = a*a%mod,b >>= 1;
		}
		return res;
	};
	auto C = [](int n,int m) -> int { return n<m?0:fac[n]*inv[n-m]%mod*inv[m]%mod; };
	int size[MAX],g[MAX],ans;
	void dfs(int u,int fa)
	{
		size[u] = 1;
		for(re int i=head[u],v; i; i=edge[i].next)
		{
			v = edge[i].to;
			if(v!=fa)
			{
				dfs(v,u);
				size[u] += size[v];
			}
		}
		fd(ans,(g[size[u]]+g[n-size[u]])%mod+(m&1?0:C(size[u],m/2)*C(n-size[u],m/2)%mod*m/2%mod));
		//printf("%lld\n",ans);
	}
	auto main = []() -> signed
	{
		freopen("meeting.in","r",stdin); freopen("meeting.out","w",stdout);
		cin >> n >> m;
		for(re int v=2,u; v<=n; v++)
		{ cin >> u; add(u,v),add(v,u); }
		fac[0] = inv[0] = 1;
		for(re int i=1; i<=n; i++)
		{ fac[i] = fac[i-1]*i%mod; }
		inv[n] = quickpow(fac[n],mod-2);
		for(re int i=n-1; i; i--)
		{ inv[i] = inv[i+1]*(i+1)%mod; }
		g[1] = (m>2)*C(n-1,m-1);
		for(re int i=1; i<=n-1; i++)
		{ g[i+1] = (g[i]-C(i-1,(m-1)/2-1)*C(n-i-1,m-(m-1)/2-1)%mod+mod)%mod,g[i] = g[i]*i%mod; }
		g[n] = n*g[n]%mod;
		//for(re int i=1; i<=n; i++) { printf("%lld\n",g[i]); }
		dfs(1,0);
		printf("%lld\n",ans);
		return 0;
	};
}
signed main()
{ return OMA::main(); }

貌似是个比较常见的套路。

T3

考场想法:显然枚举可做,于是枚举,死活过不了第二个样例...于是直接交了就。

秒竟然能枚举小数???出题人不讲武德...

正解;

二分不会。

所以用b哥的枚举....

枚举时分秒,枚举到当前的这个角度,给它转180度,找这个角度的前驱和后继,两个中跟枚举的那个角最大的就是当前的答案。

找前驱后继可以用二分查找,算出角度后记得拿360°减一下再算一个出来。

可以自己画个图理解一下。

Code
#include<cstdio>
#include<cctype>
#include<algorithm>
#define MAX 50003
#define re register
using std::sort;
using std::upper_bound;
namespace some
{
	struct stream
	{
		template<typename type>inline stream &operator >>(type &s)
		{
			bool w=0; s=0; char ch=getchar();
			while(!isdigit(ch)){ w|=ch=='-'; ch=getchar(); }
			while(isdigit(ch)){ s=(s<<1)+(s<<3)+(ch^48); ch=getchar(); }
			return s=w?-s:s,*this;
		}
	}cin;
	auto min = [](double a,double b) { return a<b?a:b; };
	auto max = [](double a,double b) { return a>b?a:b; };
}using namespace some;
namespace OMA
{
	int n;
	double beta[MAX],alpha[MAX];
	double theta,gamma,ans=361.0;
	auto main = []() -> signed
	{
		freopen("unreal.in","r",stdin); freopen("unreal.out","w",stdout);
		cin >> n;
		for(re int i=1,h,m,s; i<=n; i++)
		{
			cin >> h >> m >> s; h %= 12;
			beta[i] = m*6.0+s*0.1,alpha[i] = h*30.0+m*0.5+s*0.5/60.0;
		}
		sort(beta+1,beta+1+n),sort(alpha+1,alpha+1+n);
		beta[0] = beta[n],beta[n+1] = beta[1];
		alpha[0] = alpha[n],alpha[n+1] = alpha[1];
		for(re int h=0,p1,p2; h<12; h++)
		{
			for(re int m=0; m<60; m++)
			{
				for(re double s=0,rec1,rec2,rec3,rec4; s<60; s+=0.01)
				{
				//	double h=7,m=12,s=59.5,rec1,rec2,rec3,rec4;int p1,p2;
					theta = m*6.0+s*0.1,gamma = h*30.0+m*0.5+s/120.0;
					if(theta>=180.0) { theta -= 180.0; }
					else { theta += 180.0; }
					if(gamma>=180.0) { gamma -= 180.0; }
					else { gamma += 180.0; }
					p1 = upper_bound(beta+1,beta+1+n,theta)-beta-1;
					p2 = upper_bound(alpha+1,alpha+1+n,gamma)-alpha-1; // pre
					rec1 = 180.0-theta+beta[p1],rec2 = 180.0-beta[p1+1]+theta;
					rec3 = 180.0-gamma+alpha[p2],rec4 = 180.0-alpha[p2+1]+gamma;
					if(rec1<0.0) { rec1 += 360.0; }
					else if(rec1>=360.0) { rec1 -= 360.0; }
					if(rec2<0.0) { rec2 += 360.0; }
					else if(rec2>=360.0) { rec2 -= 360.0; }
					if(rec3<0.0) { rec3 += 360.0; }
					else if(rec3>=360.0) { rec3 -= 360.0; }
					if(rec4<0.0) { rec4 += 360.0; }
					else if(rec4>=360.0) { rec4 -= 360.0; }
					//printf("%0.5lf %0.5lf %0.5lf %0.5lf\n",rec1,rec2,rec3,rec4);
					ans = min(ans,max(max(min(rec1,360.0-rec1),min(rec2,360.0-rec2)),max(min(rec3,360.0-rec3),min(rec4,360.0-rec4))));
					//if(ans==max(max(min(rec1,360.0-rec1),min(rec2,360.0-rec2)),max(min(rec3,360.0-rec3),min(rec4,360.0-rec4))))		
				}
			}
		}
		printf("%0.5lf\n",ans);
		return 0;
	};
}
signed main()
{ return OMA::main(); }

T4

一点不会,咕了。

posted @ 2021-10-02 21:33  -OMA-  阅读(86)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end