[考试总结]noip模拟67(多校)

博客真的快要咕爆炸了。。。

看到自己上一次的博客还在 \(60\),然后非常佛。。。

今天的题目完全搞不出来,然后就写一写博客吧。。

咕了太多,那就先补一补多校联考的吧。。。

数据恢复

这个题目我们考虑贪心。

这个贪心的策略就是 \(v_i = \frac{a_i}{b_i}\),我们要选择的就是这个 \(v_i\) 最小的就行。

那么我们考虑使用 \(multiset\) 维护



#include<bits/stdc++.h>
using std::cout; using std::endl;
#define try(i,a,b) for(register int i=a;i<=b;++i)
#define throw(i,a,b) for(register int i=a;i>=b;--i)
#define go(i,x) for(register signed i=head[x],y=edge[i].ver;i;i=edge[i].next,y=edge[i].ver)
namespace xin_io
{
	#define file(x) FILE *FI = freopen(#x".in","r",stdin); FI = freopen(#x".out","w",stdout);
	#define sb(x) cout<<#x" = "<<x<<' '
	#define jb(x) cout<<#x" = "<<x<<endl
	#define debug cout<<"debug"<<endl
	#define gec() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin),p1 == p2) ? EOF : *p1 ++
	#define gc() getchar()
	#define scanf ak = scanf
	char buf[1<<20],*p1 = buf,*p2 = buf; using ll = long long; using ull = unsigned long long; int ak;
	class xin_stream{public:template<typename type>xin_stream &operator >> (type &s)
	{
		s = 0; register bool f = 0; register char ch = gc();
		while(!isdigit(ch)) f |= ch == '-',ch = gc();
		while( isdigit(ch)) s = (s << 1) + (s << 3) + (ch xor 48),ch = gc(); return s = f ? -s : s,*this;
	}}io;
}
using namespace xin_io; static const int maxn = 1e6+10,inf = 1e9+10;
#define int long long
namespace xin
{
	class xin_data
	{
		public:
			int a,b;
			double c;
	}d[maxn];
	int f[maxn],fa[maxn];
	inline int find(int x) {return x == fa[x] ? fa[x] : fa[x] = find(fa[x]);}
	int n; 
	bool vis[maxn];
	std::multiset<std::pair<double,int>>s;
	int ans = 0;
	inline void merge(int x,int y)
	{
		ans += d[y].b * d[x].a;
		d[y].b += d[x].b; d[x].b = 0;
		d[y].a += d[x].a; d[x].a = 0;
		d[y].c = (double)d[y].a / (double)d[y].b;
		fa[find(x)] = y;
	}
	inline short main()
	{
		file(data);
		io >> n;
		try(i,2,n) io >> f[i];
		try(i,1,n)
		{
			io >> d[i].a >> d[i].b; d[i].c = (double)d[i].a / (double)d[i].b;
			fa[i] = i; s.insert(std::make_pair(d[i].c,i)); vis[i] = 1;
		}
		while(!s.empty())
		{
			auto top = s.begin();
			int x = top -> second,y;
			s.erase(top); vis[x] = 0;
			if(!f[x]) continue;
			if(vis[y = find(f[x])])
			{
				d[y].c = (double)d[y].a / (double)d[y].b;
				s.erase(s.find(std::make_pair(d[y].c,y)));
				merge(x,y);
				s.insert(std::make_pair(d[y].c,y));
			}
			else merge(x,find(y));
		}
		cout<<ans<<endl;
		return 0;
	}
}
signed main() {return xin::main();}

下落的小球

这个题目考虑一个合并的操作。

我们将每个操作向上挂到树上,然后我们在之上计算答案。

对于一个相对顺序确定的长度为 \(x\) 的序列和一个长度是 \(y\) 的序列合并的方案数就是 \(\dbinom{x+y}{x}\)




#include<bits/stdc++.h>
using std::cout; using std::endl;
#define try(i,a,b) for(register int i=a;i<=b;++i)
#define throw(i,a,b) for(register int i=a;i>=b;--i)
#define go(i,x) for(register signed i=head[x],y=edge[i].ver;i;i=edge[i].next,y=edge[i].ver)
namespace xin_io
{
	#define file(x) FILE *FI = freopen(#x".in","r",stdin); FI = freopen(#x".out","w",stdout);
	#define sb(x) cout<<#x" = "<<x<<' '
	#define jb(x) cout<<#x" = "<<x<<endl
	#define debug cout<<"debug"<<endl
	#define gec() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin),p1 == p2) ? EOF : *p1 ++
	#define gc() getchar()
	#define scanf ak = scanf
	char buf[1<<20],*p1 = buf,*p2 = buf; using ll = long long; using ull = unsigned long long; int ak;
	class xin_stream{public:template<typename type>xin_stream &operator >> (type &s)
	{
		s = 0; register bool f = 0; register char ch = gc();
		while(!isdigit(ch)) f |= ch == '-',ch = gc();
		while( isdigit(ch)) s = (s << 1) + (s << 3) + (ch xor 48),ch = gc(); return s = f ? -s : s,*this;
	}}io;
}
using namespace xin_io; static const int maxn = 1e6+10,inf = 1e9+10;
#define int long long
namespace xin
{
	const int mod = 1e9+7;
	class xin_edge{public:int next,ver;}edge[maxn];
	int head[maxn],rp;
	inline void add(int x,int y) {edge[++rp].ver = y; edge[rp].next = head[x]; head[x] = rp;}
	int fac[maxn],inv[maxn],fa[maxn],a[maxn];
	int ans1[maxn],ans2[maxn],siz[maxn],r[maxn];
	int he1[maxn],he2[maxn];
	int n;
	inline int C(int n,int m) {return fac[n] * inv[m] % mod * inv[n-m] % mod;}
	inline int ksm(int x,int y,int ret = 1)
	{
		while(y)
		{
			if(y & 1) ret = ret * x % mod;
			x = x * x % mod; y >>= 1;
		}
		return ret;
	}
	void dfs(int x)
	{
		siz[x] = ans1[x] = ans2[x] = 1;
		go(i,x)
		{
			dfs(y);
			siz[x] += siz[y]; a[x] += a[y];
			he1[x] += r[y]; he2[x] += siz[y];
			(ans1[x] *= ans1[y] * C(he1[x],r[y]) % mod) %= mod;
			(ans2[x] *= ans2[y] * C(he2[x],siz[y]) % mod) %= mod;
//			sb(ans1[x]); jb(ans2[x]);
		}
		r[x] = a[x] - siz[x];
//		sb(x); sb(a[x]); jb(siz[x]);
	}
	inline short main()
	{
		file(ball);
		io >> n;
		try(i,2,n) io >> fa[i],add(fa[i],i);
		try(i,1,n) io >> a[i];//,jb(a[i]);
		fac[0] = inv[0] = 1;
		try(i,1,n) fac[i] = fac[i-1] * i % mod;
		inv[n] = ksm(fac[n],mod-2);
		throw(i,n-1,1) inv[i] = inv[i+1] * (i + 1) % mod;
		dfs(1);
		cout<<ans1[1] * ans2[1] % mod<<endl;
		return 0;
	}
}
signed main() {return xin::main();}

消失的运算符

这个在考场上是写了一个表达式求值,然后 \(\color{purple}{RE}\) 了。

是因为没清空。。。

然后就有 \(40pts\) 大分。。

这个在考场上似乎是最高的,然后因为挂了,所以只有 \(20pts\) 了,然而还是最高的



#include<bits/stdc++.h>
using std::cout; using std::endl;
#define try(i,a,b) for(register int i=a;i<=b;++i)
#define throw(i,a,b) for(register int i=a;i>=b;--i)
#define go(i,x) for(register signed i=head[x],y=edge[i].ver;i;i=edge[i].next,y=edge[i].ver)
namespace xin_io
{
	#define file(x) FILE *FI = freopen(#x".in","r",stdin); FI = freopen(#x".out","w",stdout);
	#define sb(x) cout<<#x" = "<<x<<' '
	#define jb(x) cout<<#x" = "<<x<<endl
	#define debug cout<<"debug"<<endl
	#define gec() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin),p1 == p2) ? EOF : *p1 ++
	#define gc() getchar()
	#define scanf ak = scanf
	char buf[1<<20],*p1 = buf,*p2 = buf; using ll = long long; using ull = unsigned long long; int ak;
	class xin_stream{public:template<typename type>xin_stream &operator >> (type &s)
	{
		s = 0; register bool f = 0; register char ch = gc();
		while(!isdigit(ch)) f |= ch == '-',ch = gc();
		while( isdigit(ch)) s = (s << 1) + (s << 3) + (ch xor 48),ch = gc(); return s = f ? -s : s,*this;
	}}io;
}
using namespace xin_io; static const int maxn = 1e6+10,inf = 1e9+10;
#define int long long
namespace xin
{
	const int mod = 1e9+7;
	std::stack<char> st;
	char ys[maxn];
	int top=0,jsq=0;
	int yunsuan[maxn];
	int level(char a)
	{
		if(a == '('  or  a== ')' )
			return -1;
		if(a=='+' or a=='-') 
			return 1;
		if(a=='*' or a=='/')
			return 2;
		return 0;
	}
	inline int calc(std::string &a)
	{
		jsq = top = 0; while(!st.empty()) st.pop();
		int l=a.size();
		for(int i=0;i<l-1;++i)
		{
			if(a[i] >= '0' and a[i] <= '9'  )
			{
				ys[++top]=a[i];
				ys[++top]=' ';
				continue;
			}
			if(st.empty() and ( a[i] == '+' or a[i] == '-' or a[i] == '*' or a[i] =='/'))
			{
				st.push( a[i] );
				continue;
			}
			if(a[i] == '(')
			{
				st.push( a[i] );
				continue;
			}
			if(a[i] == ')')
			{
				while(st.top() != '(')
				{
					ys[++top]=st.top();
					st.pop();
				}
				st.pop();
				continue;
			}
			if(( a[i] == '+'  or  a[i] == '-'  or  a[i] == '*')  and ( st.empty() == false))
			{
				if( level ( a[i] ) > level( st.top() ) )
				{
					st.push( a[i] );
					continue;
				}
				if(level(a[i]) <= level(st.top()))
				{
					while(!st.empty() and level (a[i])<= level(st.top()))
					{
						ys[++top]=st.top();
						st.pop();
					}
					st.push(a[i]);
					continue;
				}
			}
		}
		while(st.empty() == false)
		{
			ys[++top]=st.top();
			st.pop();
		}
		int p=1,x=0;
		while(p<=top)
		{
			if(ys[p] == '+') yunsuan[--jsq] += yunsuan[jsq+1];
			else if(ys[p] == '*') (yunsuan[--jsq] *= yunsuan[jsq+1]) %= mod;
			else
			{
				x=0;
				while(ys[p]!=' ')
					x=x*10+ys[p++]-'0';
				yunsuan[++jsq]=x;
			}
			p++;
		}
		return yunsuan[jsq];	
	}
	int a[maxn],zhi = 0;
	int n,k;
	std::string s;
	int pos[maxn],cnt = 0;
	int ans = 0;
	inline int check() 
	{
		std::string temp = s; temp += '@';
		try(i,1,zhi) temp[pos[a[i]]] = '+';
		for(auto &ch : temp) if(ch == '-') ch = '*';
//		cout<<temp<<endl; jb(calc(temp));
		return calc(temp) % mod;
	}
	void dfs()
	{
		if(zhi == k)
		{
			ans += check(); ans %= mod;
			return ;
		}
		try(i,a[zhi]+1,cnt)
		{
			a[++zhi] = i;
			dfs();
			zhi --;
		}
	}
	inline short main()
	{
		freopen("operator.in","r",stdin); freopen("operator.out","w",stdout);
		scanf("%lld%lld",&n,&k);
		std::cin >> s; int l = s.size() - 1;
		try(i,0,l)
			if(s[i] == '-') pos[++cnt] = i;
		dfs();
		cout<<ans % mod<<endl;
		return 0;
	}
}
signed main() {return xin::main();}
posted @ 2021-10-06 20:55  NP2Z  阅读(52)  评论(0编辑  收藏  举报