• NOIP58


    T1 lesson5!
    正方拓扑最短路,然后在值域上开一个权值线段树/堆/multiset。
    拓扑序枚举每个点,删去这个点贡献的答案,统计ans,再加上。

    #include<bits/stdc++.h>
    #define ls p*2
    #define rs p*2+1
    using namespace std;
    inline int read()
    {
    	int s=0,w=1;char ch=getchar();
    	while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
    	while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();}
    	return s*w;
    }
    int _max(int a,int b){return a>b?a:b;}
    int _min(int a,int b){return a<b?a:b;}
    const int N=1100000,M=5100000,INF=0x7fffffff;
    int head[2][N],cnt,n,m,dis[2][N],du[2][N],ansx,ans;
    struct rec
    {
    	int nxt,v;
    }e[2][M];
    int change[N];
    int num[N],res[M];
    void clear()
    {
    	cnt=0;
    	memset(head,0,sizeof(head));
    	memset(change,0,sizeof(change));
    	memset(du,0,sizeof(du));
    	memset(res,0,sizeof(res));
    	memset(dis,0,sizeof(dis));
    	memset(num,0,sizeof(num));
    	ansx=1;ans=n;
    }
    void add(bool id,int x,int y)
    {
    	e[id][++cnt].v=y;
    	e[id][cnt].nxt=head[id][x];
    	head[id][x]=cnt;
    }
    void pushup(int p)
    {
    	res[p]=_max(res[ls],res[rs]);
    }
    void add(int p,int l,int r,int k)
    {
    	if(l==r)
    	{
    		num[l]++;
    		if(num[l]>0)
    			res[p]=l;
    		else
    		{
    			num[l]=0;
    			res[p]=-INF;
    		}
    		return;
    	}
    	int mid=(l+r)>>1;
    	if(k<=mid)
    		add(ls,l,mid,k);
    	else
    		add(rs,mid+1,r,k);
    	pushup(p);
    }
    void del(int p,int l,int r,int k)
    {
    	if(l==r)
    	{
    		num[l]--;
    		if(num[l]>0)
    			res[p]=l;
    		else
    		{
    			num[l]=0;
    			res[p]=-INF;
    		}
    		return;
    	}
    	int mid=(l+r)>>1;
    	if(k<=mid)
    		del(ls,l,mid,k);
    	else
    		del(rs,mid+1,r,k);
    	pushup(p);
    }
    void topo(int ty)
    {
    	queue<int>q;
    	for(int i=1;i<=n;i++)
    	{
    		if(!du[ty][i])
    		{
    			if(!ty)
    				change[++change[ty]]=i;
    			q.push(i);
    		}
    	}
    	while(!q.empty())
    	{
    		int x=q.front();q.pop();
    		for(int i=head[ty][x];i;i=e[ty][i].nxt)
    		{
    			if(dis[ty][e[ty][i].v]<dis[ty][x]+1)
    				dis[ty][e[ty][i].v]=dis[ty][x]+1;
    			if(!(--du[ty][e[ty][i].v]))
    			{
    				if(!ty)
    					change[++change[ty]]=e[ty][i].v;
    				q.push(e[ty][i].v);
    			}
    		}
    	}
    }
    int main()
    {
    	freopen("johnny.in","r",stdin);
    	freopen("johnny.out","w",stdout);
    	int T=read();
    	while(T--)
    	{
    		n=read();m=read();
    		cnt=1;
    		memset(head,0,sizeof(head));
    		memset(change,0,sizeof(change));
    		memset(du,0,sizeof(du));
    		memset(res,0,sizeof(res));
    		memset(dis,0,sizeof(dis));
    		memset(num,0,sizeof(num));
    		ansx=1;ans=n;
    		for(int i=1;i<=m;i++)
    		{
    			int u,v;
    			u=read();v=read();
    			add(0,u,v);
    			add(1,v,u);
    			du[0][v]++;
    			du[1][u]++;
    		}
    		topo(0);
    		topo(1);
    		for(int i=1;i<=n;i++)
    			add(1,0,n,dis[1][i]);
    		for(int x=1;x<=n;x++)
    		{
    			for(int i=head[1][change[x]];i;i=e[1][i].nxt)
    			{
    				del(1,0,n,dis[0][e[1][i].v]+dis[1][change[x]]+1);
    			}
    			del(1,0,n,dis[1][change[x]]);
    			if(res[1]<ans||(ans==res[1]&&change[x]<ansx))
    			{
    				ansx=change[x];
    				ans=res[1];
    			}
    			for(int i=head[0][change[x]];i;i=e[0][i].nxt)
    			{
    				add(1,0,n,dis[0][change[x]]+dis[1][e[0][i].v]+1);
    			}
    			add(1,0,n,dis[0][change[x]]);
    		}
    		printf("%d %d
    ",ansx,ans);
    	}
    	return 0;
    }
    /*
    1
    6 5
    1 3
    1 4
    3 6
    3 4
    4 5
    */
    

    T2 贝尔数

    暴力处理前50项贝尔数,把 (mod) 拆分成5个小质数的积。
    矩阵乘法快速算出五个小质数下的答案,中国剩余定理合并答案。

    [egin{vmatrix} 0& 0& 0& 0& 0& 1\ 1& 1& 0& 0& 0& 0\ 0& 1& 1& 0& 0& 0\ 0& 0& 1& 1& 0& 0\ …& …& …& …& …& …\ 0&0 &0 &0 &1 &1 end{vmatrix} imes egin{vmatrix} B_1 \ B_2 \ B_3 \ B_4 \ …… \ B_p end{vmatrix} = egin{vmatrix} B_p \ B_{p+1} \ B_{p+2} \ B_{p+3} \ …… \ B_{2p-1} end{vmatrix}]

    #include<bits/stdc++.h>
    #define lowbit(x) (x&(-x))
    //#define int long long
    using namespace std;
    inline int read()
    {
    	int s=0,w=1;char ch=getchar();
    	while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
    	while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();}
    	return s*w;
    }
    int _min(int a,int b){return a<b?a:b;}
    int _max(int a,int b){return a>b?a:b;}
    int n,C[60][60][6],mo[6]={0,31,37,41,43,47},mod,B[60][6],ys[6],mi[6],ji=95041567;
    long long ans=0;
    struct jvzhen
    {
    	int n,m;
    	int s[60][60];
    	void build()
    	{
    		for(int i=1;i<=n;i++)
    			s[i][i]=1;
    		return;
    	}
    	void clear()
    	{
    		memset(s,0,sizeof s);
    	}
    	void write()
    	{
    		for(int i=1;i<=n;i++)
    		{
    			for(int j=1;j<=m;j++)
    			{
    				printf("%d ",s[i][j]);
    			}
    			puts("");
    		}
    	}
    	void write01()
    	{
    		for(int i=1;i<=n;i++)
    		{
    			for(int j=1;j<=m;j++)
    			{
    				printf("%d",s[i][j]);
    			}
    			puts("");
    		}
    	}
    };
    jvzhen operator * (jvzhen &a,jvzhen &b)
    {
    	jvzhen res;
    	res.clear();
    	res.n=a.m;
    	res.m=b.n;
    	memset(res.s,0,sizeof res.s);
    	for(int i=1;i<=a.n;i++)
    	{
    		for(int j=1;j<=b.m;j++)
    		{
    			for(int k=1;k<=a.m;k++)
    			{
    				res.s[i][j]=((res.s[i][j]+a.s[i][k]*b.s[k][j]%mod)%mod+mod)%mod;
    			}
    		}
    	}
    	return res;
    }
    jvzhen quick_pow(jvzhen a,int b)
    {
    	jvzhen res;
    	res.clear();
    	res.n=res.m=a.n;
    	res.build();
    	while(b)
    	{
    		if(b&1)
    		{
    			res=a*res;
    		}
    		a=a*a;
    		b>>=1;
    	}
    	return res;
    }
    jvzhen x[6],y[6];
    int exgcd (int a,int b ,int& x,int& y) {//函数将返回(gcd(a,b))
        if(b==0)
    	{
            x=1,y=0;
            return a;
        }    
        int d=exgcd(b,a%b,y,x);
        y-=(a/b)*x;
        return d;
    }
    int inv(int a,int b)
    {
    	int iv,tp;
    	exgcd(a,b,iv,tp);
    	return (iv%b+b)%b;
    }
    int main()
    {
    	freopen("bell.in","r",stdin);
    	freopen("bell.out","w",stdout);
    	for(int k=1;k<=5;k++)
    	{
    		mi[k]=ji/mo[k];
    		y[k].n=y[k].m=mo[k];
    		y[k].s[1][mo[k]]=1;
    		for(int i=2;i<=mo[k];i++)
    		{
    				y[k].s[i][i]=y[k].s[i][i-1]=1;
    		}
    		//y[k].write01();
    	}
    	for(int i=1;i<=5;i++)
    	{
    		C[0][0][i]=1;
    	}
    	for(int i=1;i<=50;i++)
    	{
    		for(int j=0;j<=i;j++)
    		{
    			for(int k=1;k<=5;k++)
    			{
    				C[i][j][k]=(C[i-1][j][k]+C[i-1][j-1][k])%mo[k];
    			}
    		}
    	}
    	for(int o=1;o<=5;o++)
    	{
    		B[0][o]=1;
    		for(int i=0;i<=49;i++)
    		{
    			for(int k=0;k<=i;k++)
    			{
    				B[i+1][o]+=C[i][k][o]*B[k][o]%mo[o];
    				B[i+1][o]%=mo[o];
    			}
    		}
    	}
    	for(int k=1;k<=5;k++)
    	{
    		x[k].n=mo[k];
    		x[k].m=1;
    		for(int i=1;i<=mo[k];i++)
    		{
    			x[k].s[i][1]=B[i][k];
    		}
    	}
    	int T=read();
    	while(T--)
    	{
    		ans=0;
    		n=read();
    		for(int i=1;i<=5;i++)
    		{
    			if(n<=50)
    				ys[i]=B[n][i];
    			else
    			{
    				int c=ceil(1.0*(n-mo[i])/(mo[i]-1)),gt=(n-mo[i])%(mo[i]-1);
    				if(gt==0)	gt=mo[i]-1;
    				gt++;
    				mod=mo[i];
    				//y[i].write01();
    				jvzhen tmp=quick_pow(y[i],c);
    				//tmp.write01();
    				mod=mo[i];
    				tmp=tmp*x[i];
    				//tmp.write();
    				ys[i]=tmp.s[gt][1];
    			}
    		}
    		for(int i=1;i<=5;i++)
    		{
    			mod=ji;
    			//cout<<mi[i]<<" "<<mo[i]<<endl;
    			long long tmp=(1LL*mi[i]*ys[i]%ji*inv(mi[i],mo[i])%ji+ji)%ji;
    			//cout<<tmp<<endl;
    			ans=(ans+tmp)%ji;
    		}
    		printf("%lld
    ",ans);
    	}
    	return 0;
    }
    

    T3 穿越广场

    AC自动机上DP,(f_{l,r,k,typ}) 表示匹配了长度 (l)(r)个R,匹配到AC自动机 (k) 节点,状态为包含了串 (0,1,2,12)

    #include<bits/stdc++.h>
    #define lowbit(x) (x&(-x))
    //#define int long long
    using namespace std;
    inline int read()
    {
    	int s=0,w=1;char ch=getchar();
    	while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
    	while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();}
    	return s*w;
    }
    int _min(int a,int b){return a<b?a:b;}
    int _max(int a,int b){return a>b?a:b;}
    const int N=220,mod=1e9+7;
    int m,n,f[N][N][N][4],ans;
    char c[N];
    namespace AC_zdj
    {
    	int tot;
    	struct AC_zdj
    	{
    		int son[2],num,fail;//0R 1D
    	}AC[N];
    	int change(char x)
    	{
    		if(x=='R')
    			return 0;
    		else
    			return 1;
    	}
    	void Build(char *s,int ys)
    	{
    		int len=strlen(s+1),p=0;
    		for(int i=1,gg;i<=len;i++)
    		{
    			gg=change(s[i]);
    			if(!AC[p].son[gg])
    				AC[p].son[gg]=++tot;
    			p=AC[p].son[gg];
    		}
    		AC[p].num|=ys;
    		return;
    	}
    	void get_fail()
    	{
    		AC[0].fail=0;
    		queue<int>q;
    		for(int i=0;i<2;i++)
    		{
    			if(AC[0].son[i])
    			{
    				AC[AC[0].son[i]].fail=0;
    				q.push(AC[0].son[i]);
    			}
    		}
    		while(!q.empty())
    		{
    			int u=q.front();q.pop();
    			for(int i=0;i<2;i++)
    			{
    				if(AC[u].son[i])
    				{
    					AC[AC[u].son[i]].fail=AC[AC[u].fail].son[i];
    					AC[AC[u].son[i]].num|=AC[AC[AC[u].son[i]].fail].num;
    					q.push(AC[u].son[i]);
    				}
    				else
    					AC[u].son[i]=AC[AC[u].fail].son[i];
    			}
    		}
    	}
    	void clear()
    	{
    		memset(AC,0,sizeof AC);
    		tot=0;
    	}
    };
    using namespace AC_zdj;
    int main()
    {
    	freopen("square.in","r",stdin);
    	freopen("square.out","w",stdout);
    	int T=read();
    	while(T--)
    	{
    		m=read();n=read();
    		scanf("%s",c+1);
    		Build(c,1);
    		scanf("%s",c+1);
    		Build(c,2);
    		get_fail();
    		f[0][0][0][0]=1;
    		for(int l=0;l<m+n;l++)
    		{
    			for(int r=0;r<=_min(l,m);r++)
    			{
    				for(int k=0;k<=tot;k++)
    				{
    					for(int typ=0;typ<4;typ++)
    					{
    						f[l+1][r+1][AC[k].son[0]][typ|AC[AC[k].son[0]].num]+=f[l][r][k][typ];
    						f[l+1][r+1][AC[k].son[0]][typ|AC[AC[k].son[0]].num]%=mod;
    						f[l+1][r][AC[k].son[1]][typ|AC[AC[k].son[1]].num]+=f[l][r][k][typ];
    						f[l+1][r][AC[k].son[1]][typ|AC[AC[k].son[1]].num]%=mod;
    					}
    				}
    			}
    		}
    		/*
    		for(int l=0;l<=m+n;l++)
    		{
    			for(int r=0;r<=_min(l,m);r++)
    			{
    				for(int k=0;k<=tot;k++)
    				{
    					for(int typ=0;typ<4;typ++)
    					{
    					//	printf("%d %d %d %d:%d
    ",l,r,k,typ,f[l][r][k][typ]);
    					}
    				}
    			}
    		}*/
    		ans=0;
    		for(int i=0;i<=tot;i++)
    		{
    			ans+=f[n+m][m][i][3];
    			ans%=mod;
    		}
    		printf("%d
    ",ans);
    		clear();
    		memset(f,0,sizeof f);
    		memset(c,0,sizeof c);
    	}
    	return 0;
    }
    

    T4 舞动的夜晚

    最大匹配跑完以后,对于有流量的边反向见图,没有的正向见图跑Tarjan强连通分量。一个分量内的或者匹配边两边端点的就不在答案内。其他的在。

    #include<bits/stdc++.h>
    #define lowbit(x) (x&(-x))
    //#define int long long
    using namespace std;
    inline int read()
    {
    	int s=0,w=1;char ch=getchar();
    	while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
    	while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();}
    	return s*w;
    }
    int _min(int a,int b){return a<b?a:b;}
    int _max(int a,int b){return a>b?a:b;}
    const int N=110000,M=1100000,INF=0x7fffffff;
    int n,m,T,s,t,xs,xt,dep[N],cnt=1,head[N],cur[N],zhan[N],top,belong[N],dfn[N],low[N],st,scc,ans; 
    vector<int>b[N];
    bool inq[N],vis[M];
    queue<int>q;
    struct edge
    {
    	int v,nxt,w,u;
    }e[M];
    void add(int u,int v,int w)
    {
    	e[++cnt].v=v;
    	e[cnt].u=u;
    	e[cnt].nxt=head[u];
    	e[cnt].w=w;
    	head[u]=cnt;
    }
    void make(int u,int v)
    {
    	add(u,v,1);
    	add(v,u,0);
    }
    bool SPFA()
    {
    	q.push(xs);
    	for(int i=1;i<=t;i++)
    		dep[i]=INF,cur[i]=head[i];
    	dep[xs]=0;
    	while(!q.empty())
    	{
    		int u=q.front();q.pop();
    		for(int i=head[u],v;i;i=e[i].nxt)
    		{
    			v=e[i].v;
    			if(dep[v]>dep[u]+1&&e[i].w>0)
    			{
    				dep[v]=dep[u]+1;
    				if(!inq[v])
    					q.push(v);
    			}
    		}
    	}
    	return dep[xt]!=INF;
    }
    int dfs(int u,int minn)
    {
    	if(u==xt)
    	{
    		ans+=minn;
    		return minn;
    	}
    	int used=0;
    	for(int i=cur[u],v;i;i=e[i].nxt)
    	{
    		cur[u]=i;
    		v=e[i].v;
    		if(dep[v]==dep[u]+1&&e[i].w>0)
    		{
    			int tmp=dfs(v,_min(minn,e[i].w));
    			if(tmp>0)
    			{
    				used+=tmp;
    				e[i].w-=tmp;
    				e[i^1].w+=tmp;
    				if(used==minn)
    					break;
    			}
    		}
    	}
    	return used;
    }
    void Dinic()
    {
    	while(SPFA())
    	{
    		dfs(xs,INF);
    	}
    }
    void Tarjan(int cur)
    {
        dfn[cur]=low[cur]=++st;
        zhan[++top]=cur;inq[cur]=true;
        for(auto v:b[cur])
        {
            if(dfn[v]==0)
            {
                Tarjan(v);
                low[cur]=_min(low[cur],low[v]);
            }
            else
            {
                if(inq[v]==true)
                {
                    low[cur]=min(low[cur],dfn[v]);
                }
            }
        }
        if(low[cur]==dfn[cur])
        {
            scc++;
            int ding;
            do
            {
                ding=zhan[top];
                inq[ding]=false;
                zhan[top--]=0;
                belong[ding]=scc;
            }while(ding!=cur);
        }
        return;
    }
    int main()
    {
    	freopen("night.in","r",stdin);
    	freopen("night.out","w",stdout);
    	n=read();m=read();T=read();
    	s=n+m+1;t=s+1;
    	for(int i=1,u,v;i<=T;i++)
    	{
    		u=read();v=read();
    		make(u,v+n);
    	}
    	for(int i=1;i<=n;i++)
    		make(s,i);
    	for(int i=1;i<=m;i++)
    		make(i+n,t);
    	xs=s;xt=t;
    	Dinic();
    	for(int i=2,u,v;i<=cnt;i++)
    	{
    		if(e[i].w)
    		{
    			u=e[i].u;v=e[i].v;
    			b[u].push_back(v);
    			//printf("%d %d
    ",u,v);
    		}
    	}
    	for(int i=1;i<=n+m+2;i++)
    	{
    		if(!dfn[i])
    			Tarjan(i);
    	}
    	for(int i=3,u,v;i<=cnt;i+=2)
    	{
    		u=e[i].u;
    		v=e[i].v;
    		if(belong[u]==belong[v]||e[i].w>0)
    		{
    			vis[i]=1;
    		}
    	}
    	ans=0;
    	for(int i=1;i<=T;i++)
    	{
    		if(!vis[i*2+1])
    			ans++;
    	}
    	printf("%d
    ",ans);
    	for(int i=1;i<=T;i++)
    	{
    		if(!vis[i*2+1])
    			printf("%d ",i);
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    linux
    ansible
    语法糖
    jupyter login
    hadoop patch
    ganglia
    unixbench安装使用
    linux使用FIO测试磁盘的iops
    cpu事实负载使用top命令
    phoronix-test-suite测试云服务器
  • 原文地址:https://www.cnblogs.com/HKHbest/p/15331077.html
Copyright © 2020-2023  润新知