[考试总结]noip模拟58

博客不能再咕了,所以今天趁着还没有忘干净就赶紧补补。

这场考试还是比较凄惨的。。。。

自己认为贝尔数还是比较可做的,然后发现这个模数是个合数。

当场自闭,认为 \(C\) 根本无法计算。。。

然后想了一个比较嗖的方法。。。。

写了一个 \(.py\) 然后直接暴力计算之后取模。。

本以为自己牛逼得一批,然后认为很多分数到手,结果。。。

\(python\) 的除法计算直接化成浮点数,然后我的精度就爆炸了。。。

非常生气!!!

然后 \(T1\) 偏偏是没有往 \(topo\) 那里去想。

Lesson5!

这个就是一个拓扑,一次拓扑之后我们就能找到一个有向图的任意起点的最短路,之后我们记忆化一下。

那么我们使用 \(multiset\) 来维护一下子删点就行。



%: pragma GCC optimize(2)
#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(a) FILE *FI = freopen(#a".in","r",stdin); FI = freopen(#a".out","w",stdout);
	#define debug cout<<"debug"<<endl
	#define sb(x) cout<<#x" = "<<x<<' '
	#define jb(x) cout<<#x" = "<<x<<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 &x)
	{
		register type s = 0; register int f = 1; register char ch = gc();
		while(!isdigit(ch)) {if(ch == '-') f = -1; ch = gc();}
		while( isdigit(ch)) s = (s << 1) + (s << 3) + (ch  xor 48),ch = gc(); return x = s * f,*this;
	}}io;
}
using namespace xin_io; static const int maxn = 1e6+10,inf = 1e9+7,mod = 998244353; const ll llinf = 1e18+7;
auto max = [](int x,int y)->int{return x > y ? x : y;}; auto min = [](int x,int y)->int{return x < y ? x : y;};
namespace xin
{
	class xin_edge{public:int next,ver;}edge[maxn];
	int head[maxn],rp;
	auto add = [](int x,int y) -> void{edge[++rp].ver = y; edge[rp].next = head[x]; head[x] = rp;};
	int T,n,m;
	int ind[maxn],cind[maxn];
	int maxx;
	int id[maxn];
	std::multiset<int,std::greater<int> >s;
	class xin_data
	{
		public:
			int x,tim;
			xin_data(){}
			xin_data(int x,int tim):x(x),tim(tim){}
	};
	bool vis[maxn];
	auto topo = []() -> void
	{
		std::queue<xin_data>q;
		try(i,1,n) if(!ind[i] and !vis[i]) q.push(xin_data(i,0));
		while(q.size())
		{
			xin_data x = q.front(); q.pop();
//			sb(x.x); jb(x.tim);
			maxx = max(maxx,x.tim);
			go(i,x.x)
				if(!--ind[y] and !vis[y])
					q.push(xin_data(y,x.tim+1));
		}
	};
	int f[maxn],g[maxn];
	auto getid = []() -> void
	{
		int x = 0,tot = 0;
		try(i,1,n) if(!ind[i]) id[++tot] = i;//,cout<<i<<' ';
		while(tot < n)
		{
			x++; 
			go(i,id[x])
				if(!--ind[y]) id[++tot] = y;
		}
	};
	std::pair<int,int>ans = std::make_pair(inf,inf);
	std::vector<int>vec[maxn];
	int mark[maxn];
	inline short main()
	{
		file(johnny);
		io >> T;
		while(T--)
		{
			io >> n >> m;
			try(i,1,m) 
			{
				register int x,y; io >> x >> y;
				add(x,y); ind[y] ++; 
				vec[y].push_back(x);
			}
			if(!m) {cout<<1<<' '<<0<<endl; continue;}
//			try(i,1,n) if(!ind[i]) jb(i);


			getid();
//			try(i,1,n) cout<<id[i]<<' ';
			try(i,1,n)
			{
				register int x = id[i]; f[x] = max(f[x],1);
				go(bian,x) f[y] = max(f[y],f[x] + 1);
			}
			throw(i,n,1) 
			{
				register int x = id[i]; g[x] = max(g[x],1);
				go(bian,x) g[x] = max(g[x],g[y] + 1);
			}
//			try(i,1,n) cout<<f[i]<<' '<<g[i]<<endl;
			try(i,1,n) s.insert(g[i]),s.insert(0);
			try(i,1,n)
			{
				register int x = id[i];
				for(auto y : vec[x])
					if(s.find(f[y] + g[x]) != s.end())
						s.erase(s.find(f[y] + g[x]));
					else mark[f[y] + g[x]] ++;
				if(s.find(g[x]) != s.end())
					s.erase(s.find(g[x]));
				else mark[g[x]] ++;
				register int temp = *s.begin();
				if(temp < ans.second) ans.second = temp,ans.first = x;
				else if(temp == ans.second) ans.first = min(ans.first,x);
				go(bian,x)
				{
					if(mark[f[x] + g[y]])
						mark[f[x] + g[y]] --;
					else s.insert(f[x] + g[y]);
				}
				if(mark[f[x]]) mark[f[x]] --;
				else s.insert(f[x]);
			}
			s.clear();
			
/*
			try(i,1,n)
			{
				memcpy(ind,cind,sizeof(int) * (n + 1));
//				try(j,1,n) jb(ind[j]);
				vis[i] = 1;  maxx = -inf;
				go(bian,i) ind[y] --;
				topo();
//				jb(maxx);
				if(maxx < ans.second) ans = std::make_pair(i,maxx);
//				sb(i); jb(maxx);
				vis[i] = 0;
			}*/
			cout<<ans.first<<' '<<ans.second - 1<<endl;
			memset(head,0,sizeof(int) * (n + 1)); memset(f,0,sizeof(int) * (n + 1));
			memset(ind,0,sizeof(int) * (n + 1));  memset(g,0,sizeof(int) * (n + 1));
			try(i,1,n) vec[i].clear();
			ans = std::make_pair(inf,inf); rp = 0;
		}
		return 0;
	}
}
signed main() {return xin::main();}

贝尔数

这个暂时只想说说这个的暴力。。。

这个东西组合数是可以计算的。

我们用杨辉三角递推就行,这样是合数也是不用害怕的。。



#include<bits/stdc++.h>
using std::cout; using std::endl;
#define int long long
#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];i;i=edge[i].next)
namespace xin_io
{
	#define file(a) FILE *FI = freopen(#a".in","r",stdin); FI = freopen(#a".out","w",stdout);
	#define debug cout<<"debug"<<endl
	#define sb(x) cout<<#x" = "<<x<<' '
	#define jb(x) cout<<#x" = "<<x<<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 &x)
	{
		register type s = 0; register int f = 1; register char ch = gc();
		while(!isdigit(ch)) {if(ch == '-') f = -1; ch = gc();}
		while( isdigit(ch)) s = (s << 1) + (s << 3) + (ch  xor 48),ch = gc(); return x = s * f,*this;
	}}io;
}
using namespace xin_io; static const int maxn = 1e6+10,inf = 1e9+7; const ll llinf = 1e18+7;
#define int long long
namespace xin
{
	const int mod = 95041567;
	int bell[maxn];
	int C[maxn/1000+11][maxn/1000+11];
	inline short main()
	{
		file(bell);

		int ms = 1010;

		C[0][0] = 1;
		try(i,1,ms) try(j,i,ms) C[j][i] = (C[j-1][i] + C[j-1][i-1]) % mod;
		bell[0] = bell[1] = 1;
		try(n,1,ms)
		{
			int tot = 0;
			try(k,0,n) (tot += C[n][k] * bell[k] % mod) %= mod;
			bell[n+1] = tot;
		}

		int T; io >> T;

		while(T--)
		{
			register int x; io >> x;
			cout<<bell[x+1]<<endl;
		}
		return 0;
	}
}
signed main() {return xin::main();}

穿越广场

\(Ac\) 自动机的 \(dp\)

\[(f[i+1][ j ][t[k].son[0]][l|state[t[k].son[0]]] += f[i][j][k][l]) \%= mod;\\ (f[i+1][j+1][t[k].son[1]][l|state[t[k].son[1]]] += f[i][j][k][l]) \%= mod; \]



#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 debug cout<<"debug"<<endl
	#define jb(x) cout<<#x" = "<<x<<endl;
	#define sb(x) cout<<#x" = "<<x<<' '
	#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 &x)
	{
		register type s = 0; register int f = 1; register char ch = gc();
		while(!isdigit(ch)) {if(ch == '-') f = -1; ch = gc();}
		while( isdigit(ch)) s = (s << 1) + (s << 3) + (ch  xor 48),ch = gc(); return x = s * f,*this;
	}}io;
	#define scanf ak = scanf
}
using namespace xin_io; static const int maxn = 2e3+10,inf = 1e9+7; const ll llinf = 1e18+7;
#define int long long
namespace xin
{
	const int mod = 1e9+7;
    class xin_trie
    {
        public:
            int son[2];
            int fail;
    }t[maxn];
    int cnt = 1;
	int state[maxn];
    inline void insert(char *s,int num)
    {
        register int u = 1;
        for(register int i=0;s[i];++i)
        {
            register int bian = s[i] == 'R';
            if(!t[u].son[bian]) t[u].son[bian] = ++cnt;
            u = t[u].son[bian];
        }
		state[u] |= num;
//		jb(state[u]);
    }
    inline void getfail()
    {
        std::queue < int > q; q.push(1);
		t[0].son[0] = t[0].son[1] = 1;
		while(q.size())
		{
			register int u = q.front(); q.pop();
			for(register int i=0;i<=1;++i)
				if(t[u].son[i])
					t[t[u].son[i]].fail = t[t[u].fail].son[i],q.push(t[u].son[i]);	
				else 
					t[u].son[i] = t[t[u].fail].son[i];
		}
    }	
	int n,m,T;
	int f[201][201][201][4];

	auto work = []() -> void
	{
		int ans = 0;
		try(i,1,cnt)
		{
			for(register int j=i;j;j=t[j].fail)
				state[i] |= state[j];
//			jb(state[i]);
		}
		f[0][0][1][0] = 1;
		try(i,0,n+m-1) try(j,0,m) try(k,1,cnt) try(l,0,3)
		{
			(f[i+1][ j ][t[k].son[0]][l|state[t[k].son[0]]] += f[i][j][k][l]) %= mod;
			(f[i+1][j+1][t[k].son[1]][l|state[t[k].son[1]]] += f[i][j][k][l]) %= mod;
		}
		try(i,1,cnt) (ans += f[n+m][m][i][3]) %= mod;//,jb(f[n+m][m][i][3]);
		printf("%lld\n",ans);
	};


	char s1[maxn],s2[maxn];
	auto clear = []() -> void
	{
		memset(f,0,sizeof(f)); cnt = 1; memset(t,0,sizeof(t));
		memset(state,0,sizeof(state));
	};
	inline short main()
	{
		file(square);
		scanf("%lld",&T);
		while(T--)
		{
			clear();
			scanf("%lld%lld",&m,&n);
			scanf("%s%s",s1,s2);
			insert(s1,1); insert(s2,2);
			getfail();
			work();	
		}
		return 0;
	}
}
signed main() {return xin::main();}

舞动的夜晚

这个题目的部分分数就是一个二分图的最大匹配,这个我们可以用 \(dinic\) 跑一个最大流。

但其实我们还有一个很好的方法就是匈牙利算法,这个可以在严格 \(\mathcal O(nm)\) 的复杂度中计算出二分图的最大匹配。



#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(a) FILE *FI = freopen(#a".in","r",stdin); FI = freopen(#a".out","w",stdout);
	#define debug cout<<"debug"<<endl
	#define sb(x) cout<<#x" = "<<x<<' '
	#define jb(x) cout<<#x" = "<<x<<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 &x)
	{
		register type s = 0; register int f = 1; register char ch = gc();
		while(!isdigit(ch)) {if(ch == '-') f = -1; ch = gc();}
		while( isdigit(ch)) s = (s << 1) + (s << 3) + (ch  xor 48),ch = gc(); return x = s * f,*this;
	}}io;
}
using namespace xin_io; static const int maxn = 1e6+10,inf = 1e9+7,mod = 998244353; const ll llinf = 1e18+7;
namespace xin
{
	class xin_edge{public:int next,ver;}edge[maxn];
	class xin_data{public:int x,y;}d[maxn];
	int head[maxn],rp;
	auto add = [](int x,int y) -> void{edge[++rp].ver = y; edge[rp].next = head[x]; head[x] = rp;};
	bool vis[maxn];
	int mat[maxn],ans = 0;
	int zhuanx,zhuany;
	bool dfs(int x)
	{
		go(i,x) if(!vis[y] and zhuanx != x and zhuany != y)
		{
			vis[y] = 1;
			if(!mat[y] or dfs(mat[y])) {mat[y] = x; return true;}
		}
		return false;
	}
	int n,m,t;
	int out[maxn],top;
	inline short main()
	{
		file(night);

		io >> n >> m >> t;
		try(i,1,t)
		{
			register int x,y; io >> x >> y;
			y += n; add(x,y); add(y,x);
			d[i].x = x; d[i].y = y;
		}
//		vis[2] = vis[4] = 1;
//		mat[4] = 2;
//		zhuanx = 2; zhuany = 4;
		try(i,1,n)
		{
			memset(vis,0,sizeof(bool) * (n + m + 1));
			if(dfs(i)) ans ++;
		}
//		try(i,1,n+m) sb(i),jb(mat[i]);
		int comp = ans;
		try(i,1,t)
		{
			memset(mat,0,sizeof(int) * (n + m + 1));
			zhuanx = d[i].x; zhuany = d[i].y; ans = 0;
			try(i,1,n)
			{
				memset(vis,0,sizeof(bool) * (n + m +  1));
				if(dfs(i)) ans ++;
			}
			if(ans + 1 < comp) out[++top] = i;
		}
//		cout<<ans<<endl;
		cout<<top<<endl;
		try(i,1,top)
			cout<<out[i]<<' ';
		return 0;
	}
}
signed main() {return xin::main();}
posted @ 2021-09-25 20:02  NP2Z  阅读(32)  评论(0编辑  收藏  举报