[考试总结]noip模拟51

茅山道术

似乎这个一个普通的 \(dp\) 就能搞掉。。

\[f_i = f_{i-1} + [i - pre_{a_i} > 1] * f_{pre_{a_i}} \]

愉快 \(ac\)



#include<bits/stdc++.h>
using std::cout; using std::endl;
#define try(i,a,b) for(register signed i=a;i<=b;++i)
#define throw(i,a,b) for(register signed 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 sb(x) cout<<#x" = "<<x<<' '
	#define jb(x) cout<<#x" = "<<x<<endl
	#define debug cout<<"debug"<<endl
	#define gc() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin),p1 == p2) ? EOF : *p1++
	char buf[1<<20],*p1 = buf,*p2 = buf; int ak; typedef long long ll; typedef unsigned long long ull;
	class xin_stream{public:template<typename type>inline xin_stream &operator >> (type &s)
	{
		register int f = 0;s = 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 = 1e7+10,inf = 1e9+7; const ll llinf = 1e18+7;
namespace xin
{
	const int mod = inf;
	int f[maxn];
	int pre[maxn],a[maxn];
	int n;
	inline short main()
	{
		freopen("magic.in","r",stdin); freopen("magic.out","w",stdout);
		io >> n;
		try(i,1,n) io >> a[i],pre[i] = n + 3;
		f[1] = 1; pre[a[1]] = 1;
		try(i,2,n)
		{
//			sb(a[i]); jb(pre[a[i]]);
			f[i] = (f[i-1] + (i - pre[a[i]] > 1) * f[pre[a[i]]]) % mod;
			pre[a[i]] = i;
		}
		cout<<f[n]<<endl;
		return 0;
	}
}
signed main() {return xin::main();}

泰拳警告

可以发现式子:

\[Ans = \sum_k (p+1)(\frac{p}{p+2})^k(\frac{1}{p+2})^{n-k}\dbinom{n}{k} \sum_{numwin}\dbinom{n-k}{sheng} \]

\[= \sum_k \frac{\;p^k\;(p+1)}{(p+2)^n} \frac{2^n - \dbinom{n/2}{k}(if\;(n-k)is\;even)}{n} \]

然后预处理一下

\(\mathcal O(n)\)



#include<bits/stdc++.h>
using std::cout; using std::endl;
#define try(i,a,b) for(register signed i=a;i<=b;++i)
#define throw(i,a,b) for(register signed 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 sb(x) cout<<#x" = "<<x<<' '
	#define jb(x) cout<<#x" = "<<x<<endl
	#define debug cout<<"debug"<<endl
	#define gc() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin),p1 == p2) ? EOF : *p1++
	char buf[1<<20],*p1 = buf,*p2 = buf; int ak; typedef long long ll; typedef unsigned long long ull;
	class xin_stream{public:template<typename type>inline xin_stream &operator >> (type &s)
	{
		register int f = 0;s = 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 = 3e6+10,inf = 1e9+7; const ll llinf = 1e18+7;
#define int long long
namespace xin
{
	const int mod = 998244353;
	auto ksm = [](int x,int y,int ret = 1) -> int
	{
		while(y)
		{
			if(y & 1) ret = ret * x % mod;
			x = x * x % mod; y >>= 1;
		}
		return ret;
	};
	int n,p,ans = 0;

	int fac[maxn],invfac[maxn],fangp[maxn],fang2[maxn];
	auto C = [](int n,int m) -> int
	{
		if(m > n) return 0;
		if(m == n) return 1;
		return fac[n] * invfac[m] % mod * invfac[n-m] % mod;
	};
	
	inline short main()
	{
		freopen("fight.in","r",stdin); freopen("fight.out","w",stdout);

		io >> n >> p;

		fac[0] = fac[1] = 1; fangp[1] = p; fangp[0] = 1;
		
		try(i,2,n) fac[i] = fac[i-1] * i % mod,fangp[i] = fangp[i-1] * p % mod;
		invfac[n] = ksm(fac[n],mod-2);
		throw(i,n-1,1) invfac[i] = invfac[i+1] * (i + 1) % mod;
		invfac[0] = 1;

		int pinv = ksm(ksm(p + 2,n),mod - 2),inv2 = ksm(2,mod-2);
//		jb(pinv);
	
		fang2[1] = 2; fang2[0] = 1;
		try(i,2,n) fang2[i] = fang2[i-1] * 2 % mod;

		try(ping,0,n-1)
		{
			register int k = n - ping;
			int temp = (fang2[k] - (!(k & 1)) * C(k,k/2) + mod) % mod * inv2 % mod;
			(ans += fangp[ping] * (ping + 1) % mod * pinv % mod * C(n,ping) % mod * temp % mod) %= mod;
		}
		
		cout<<ans<<endl;
		
		return 0;
	}
}
signed main() {return xin::main();}

万猪拱塔

挺妙的

就是我们将每一个选择的权值染黑,然后如果合法组成一个矩形,那么图中一定有四个只被染了一个的小正方形。

然后我们分四个位置转移。

然后没啥了。。

对了,要线段树维护信息。



%: pragma GCC optimize("Ofast,unroll-loops")
#include<bits/stdc++.h>
using std::cout; using std::endl;
#define try(i,a,b) for(signed i=a;i<=b;++i)
#define throw(i,a,b) for(signed i=a;i>=b;--i)
#define go(i,x) for(signed i=head[x],y=edge[i].ver;i;i=edge[i].next,y=edge[i].ver)
namespace xin_io
{
	#define file(a,b) freopen(#a"","r",stdin),freopen(#b"","w",stdout)
	#define sb(x) cout<<#x" = "<<x<<' '
	#define jb(x) cout<<#x" = "<<x<<endl
	#define debug cout<<"debug"<<endl
	#define gc() p1 == p2 and (p2 = (p1 = buf) + fread(buf,1,1<<20,stdin),p1 == p2) ? EOF : *p1++
	char buf[1<<20],*p1 = buf,*p2 = buf; int ak; typedef long long ll; typedef unsigned long long ull;
	class xin_stream{public:template<typename type>inline xin_stream &operator >> (type &s)
	{
		register int f = 0;s = 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+7; const ll llinf = 1e18+7;
namespace xin
{
	auto min = [](int x,int y) -> int{return x < y ? x : y;};
	auto max = [](int x,int y) -> int{return x > y ? x : y;};
	const int mod = 998244353;
	class xin_seg
	{
		private:
			#define ls(fa) (fa << 1)
			#define rs(fa) (fa << 1 | 1)
			inline void up(int fa)
			{
				if(t[ls(fa)].minn > t[rs(fa)].minn)
					t[fa].minn = t[rs(fa)].minn,t[fa].cnt = t[rs(fa)].cnt,t[fa].s = t[rs(fa)].s;

				if(t[ls(fa)].minn == t[rs(fa)].minn)
					t[fa].minn = t[ls(fa)].minn,t[fa].cnt = t[ls(fa)].cnt + t[rs(fa)].cnt,t[fa].s = t[ls(fa)].s + t[rs(fa)].s;

				if(t[ls(fa)].minn < t[rs(fa)].minn)
					t[fa].minn = t[ls(fa)].minn,t[fa].cnt = t[ls(fa)].cnt,t[fa].s = t[ls(fa)].s;
			}
			inline void down(int fa)
			{
				if(!t[fa].debt) return ;
				
				t[ls(fa)].minn += t[fa].debt; t[rs(fa)].minn += t[fa].debt;
				t[ls(fa)].debt += t[fa].debt; t[rs(fa)].debt += t[fa].debt;

				t[fa].debt = 0;
			}
		public:
			class xin_tree{public:int debt,minn,cnt,s;}t[maxn<<2];
			void build(int fa,int l,int r)
			{
				if(l == r) return t[fa].minn = inf,void();
				register int mid = l + r >> 1;
				build(ls(fa),l,mid); build(rs(fa),mid+1,r);
				up(fa);
			}
			void update(int fa,int l,int r,int ql,int qr,int val)
			{
				//sb(ql); sb(qr); sb(l); jb(r);
				if(ql > qr) return ;
				if(ql <= l and qr >= r)
				{
					t[fa].minn += val; t[fa].debt += val;
					return;
				}
				down(fa);
				register int mid = l + r >> 1;
				if(ql <= mid) update(ls(fa),l,mid,ql,qr,val);
				if(qr >  mid) update(rs(fa),mid+1,r,ql,qr,val);
				up(fa);
			}
			void modify(int fa,int l,int r,int pos,int val)
			{
				if(l == r)
				{
					t[fa].minn = val; t[fa].s = l; t[fa].cnt = 1;
					return ;
				}
				register int mid = l + r >> 1;
				if(pos <= mid) modify(ls(fa),l,mid,pos,val);
				else modify(rs(fa),mid+1,r,pos,val);
				up(fa);
			}
	}t;

	int n,m,ans = 0;
	class xin_data
	{
		public:
			int x,y;
			xin_data(){}
			xin_data(int x,int y):x(x),y(y){}
	}d[maxn];
	int temp[5];
	int **a;

	inline short main()
	{
		file(pig.in,pig.out);
		register std::function<void()> zhuan = [](){};


		io >> n >> m;
		a = new int *[n + 3];
		try(i,1,n) {a[i] = new int[m+3]; try(j,1,m) io >> a[i][j],d[a[i][j]] = xin_data(i,j);}
		a[n + 1] = new int[m+3]; a[0] = new int [m + 3];
		try(i,0,n+1) a[i][0] = a[i][m+1] = inf;
		try(j,0,m+1) a[0][j] = a[n+1][j] = inf;
		
		t.build(1,1,n*m);

		try(r,1,n*m)
		{
			register int x = d[r].x,y = d[r].y;
			
			auto work1 = [=]()mutable -> void //zuo_shang
			{
				temp[1] = a[x-1][y-1]; temp[2] = a[x-1][y]; temp[3] = a[x][y-1]; temp[4] = a[x][y];
				std::sort(temp+1,temp+5);
				int pos; try(i,1,4) if(temp[i] == r) {pos = i;temp[i] = r - 1; break;}
				int f = 1;
				throw(i,pos,1)
					t.update(1,1,n*m,temp[i-1]+1,temp[i],f),f = -f;
			};
			
			auto work2 = [=]()mutable -> void //you_shang
			{
				temp[1] = a[x][y-1]; temp[2] = a[x+1][y-1]; temp[3] = a[x+1][y]; temp[4] = a[x][y];
				std::sort(temp+1,temp+5);
				int pos; try(i,1,4) if(temp[i] == r) {pos = i; temp[i] = r - 1;break;}
				int f = 1;
				throw(i,pos,1)
					t.update(1,1,n*m,temp[i-1]+1,temp[i],f),f = -f;
			};
			
			auto work3 = [=]()mutable -> void //zuo_xia
			{
				temp[1] = a[x][y]; temp[2] = a[x-1][y]; temp[3] = a[x-1][y+1]; temp[4] = a[x][y+1];
				std::sort(temp+1,temp+5);
				int pos; try(i,1,4) if(temp[i] == r) {pos = i; temp[i] = r - 1;break;}
				int f = 1;
				throw(i,pos,1)
					t.update(1,1,n*m,temp[i-1]+1,temp[i],f),f = -f;
			};
			
			auto work4 = [=]()mutable -> void //you_xia
			{
				temp[1] = a[x][y]; temp[2] = a[x][y+1]; temp[3] = a[x+1][y]; temp[4] = a[x+1][y+1];
				std::sort(temp+1,temp+5);
				int pos; try(i,1,4) if(temp[i] == r) {pos = i; temp[i] = r - 1;break;}
				int f = 1;
				throw(i,pos,1)
					t.update(1,1,n*m,temp[i-1]+1,temp[i],f),f = -f;
			};

			t.modify(1,1,n*m,r,4);
			work1(); work2(); work3(); work4();
			ans += (t.t[1].minn == 4) * (r * t.t[1].cnt - t.t[1].s + t.t[1].cnt);
			ans %= mod;
		}
		
		cout<<ans<<endl;

		return 0;
	}
}
signed main() {return xin::main();}

抑郁刀法

咕了。。。。

上一篇:Meet in another world, enjoy tasty food!(思维)


下一篇:2021团体程序设计天梯赛 L1-7 天梯赛的善良