模拟题大集合(2)

2021-11-13 18:29:04 星期六

异或 2

高精+记忆化搜索即可。

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<unordered_map>
#include<map>
#include<vector>
#include<map>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	typedef unsigned __int128 _uint;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("rox.in","r",stdin);freopen("rox.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const ll mod=1e16;
	struct bigint{
		int wei;std::vector<ll>p;_uint hash;
		inline void gethash(){F(i,1,wei)hash=hash*131+p[i];}
		friend bool operator <(bigint a,bigint b){
			if(a.wei!=b.wei)return a.wei>b.wei?0:1;
			D(i,a.wei,1){
				if(a.p[i]>b.p[i])return 0;
				return 1;
			}return 1;
		}
		inline void print(){if(!wei){putchar('0');putchar(' ');return;}pf("%lld",p[wei]);D(i,wei-1,1)pf("%016lld",p[i]);pf(" ");}
		inline void clear(){wei=0;p.resize(0);}
		inline void init(){
			static char s[510];
			scanf("%s",s+1);int n=strlen(s+1);
			p.resize(n/16+10);
			ll now=0,base=1;int cnt=0;
			D(i,n,1){
				cnt++;
				now+=(s[i]-'0')*base;
				base*=10;
				if(cnt==16)p[++wei]=now,cnt=0,base=1,now=0;
			}if(now)p[++wei]=now;
		}
		inline bigint operator -(bigint b){
			bigint c;c.clear();c.wei=wei+5;c.p.resize(c.wei+2);
			F(i,1,wei){
				c.p[i]+=p[i]-b.p[i];
				if(c.p[i]<0)c.p[i+1]--,c.p[i]+=mod;
			}while(!c.p[c.wei]&&c.wei>0)c.wei--;
			c.gethash();return c;
		}
		inline bigint operator *(int b){
			bigint c;c.clear();c.wei=wei+2;c.p.resize(c.wei+2);
			F(i,1,wei){
				c.p[i]+=p[i]*b;
				c.p[i+1]+=c.p[i]/mod;
				c.p[i]%=mod;
			}while(!c.p[c.wei]&&c.wei>0)c.wei--;
			c.gethash();return c;
		}
		inline bigint operator +(bigint b){
			bigint c;c.clear();c.wei=max(wei,b.wei)+5;c.p.resize(c.wei+2);
			F(i,1,c.wei){
				if(i<=wei)c.p[i]+=p[i];
				if(i<=b.wei)c.p[i]+=b.p[i];
				c.p[i+1]+=c.p[i]/mod;
				c.p[i]%=mod;
			}while(!c.p[c.wei]&&c.wei>0)c.wei--;
			c.gethash();return c;
		}
		inline bigint operator -(int x){
			bigint c;c.clear();c.wei=wei;c.p.resize(c.wei+5);
			c.p[1]=-x;
			F(i,1,c.wei){
				c.p[i]+=p[i];
				if(c.p[i]<0)c.p[i]+=mod,c.p[i+1]--;
			}while(!c.p[c.wei]&&c.wei>0)c.wei--;
			c.gethash();return c;
		}
		inline bigint operator /(int x){
			bigint c;c.clear();
			c.wei=wei;c.p.resize(wei+5);
			F(i,1,wei)c.p[i]=p[i];
			D(i,wei,1)c.p[i-1]+=mod*(c.p[i]%x),c.p[i]/=x;
			while(!c.p[c.wei]&&c.wei>0)c.wei--;
			c.gethash();return c;
		}
	}base[5],begin;
	std::map<_uint,bigint>mp;
	inline void init(){
		base[3].wei=1,base[3].p.resize(2),base[3].p[1]=6;
		base[4].wei=1,base[4].p.resize(2),base[4].p[1]=4;
	}
	inline bigint f(bigint x){
		if(x.wei==1&&x.p[1]<=4)return base[x.p[1]];
		if(x.wei==0)return base[0];
		if(mp[x.hash].p.size())return mp[x.hash];
		if(x.p[1]&1)return mp[x.hash]=f(x/2)*4+(x/2)*6;
		else return mp[x.hash]=f(x/2)*2+f(x/2-1)*2+x*2-4;
	}
	inline short main(){
		file();
		init();
		begin.init();
		f(begin).print();pn();
		return 0;
	}
}
signed main(){return EMT::main();}

异或

建出两棵字典数分别管理左右两边的区间。
维护一个数组表示中间的数每一位是啥有多少贡献即可。

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cassert>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("xor.in","r",stdin);freopen("xor.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(ll x){pf("%lld ",x);}inline void pn(){pf("\n");}
	const int N=5e5+10;
	ll cnt[35][2];
	struct tire{int son[N*32][2],siz[N*32],tot;}t1,t2;
	inline void insert(int p){
		int now1=0,now2=0;
		D(i,30,0){
			if((p>>i)&1){
				cnt[i][1]+=t2.siz[t2.son[now2][0]];
				if(!t1.son[now1][1])t1.son[now1][1]=++t1.tot;
				now1=t1.son[now1][1];now2=t2.son[now2][1];
				t1.siz[now1]++;
			}else{
				cnt[i][0]+=t2.siz[t2.son[now2][1]];
				if(!t1.son[now1][0])t1.son[now1][0]=++t1.tot;
				now1=t1.son[now1][0];now2=t2.son[now2][0];
				t1.siz[now1]++;
			}
		}
	}
	inline void del(int p){
		int now1=0,now2=0;bool fl=1;
		D(i,30,0){
			if((p>>i)&1){
				if(fl)cnt[i][0]-=t1.siz[t1.son[now1][0]];
				if(fl)now1=t1.son[now1][1];if(!now1)fl=0;
				now2=t2.son[now2][1];
				t2.siz[now2]--;
			}else{
				if(fl)cnt[i][1]-=t1.siz[t1.son[now1][1]];
				if(fl)now1=t1.son[now1][0];if(!now1)fl=0;
				now2=t2.son[now2][0];
				t2.siz[now2]--;
			}
		}
	}
	inline void ins(int p){
		int now=0;
		D(i,30,0){
			if((p>>i)&1){
				if(!t2.son[now][1])t2.son[now][1]=++t2.tot;
				now=t2.son[now][1];
				t2.siz[now]++;
			}else{
				if(!t2.son[now][0])t2.son[now][0]=++t2.tot;
				now=t2.son[now][0];
				t2.siz[now]++;
			}
		}
	}
	int n,a[N];ll ans;
	inline short main(){
		file();
		n=read();
		F(i,1,n)a[i]=read(),ins(a[i]);
		F(i,1,n){
			del(a[i]);
			D(j,30,0)ans+=cnt[j][(a[i]>>j)&1];
			insert(a[i]);
		}pi(ans);
		return 0;
	}
}
signed main(){return EMT::main();}

子集和

反着做一遍背包即可。

Code
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
namespace EMT{
	typedef long long ll;typedef double db;
	#define F(i,a,b) for(int i=a;i<=b;i++)
	#define D(i,a,b) for(int i=a;i>=b;i--)
	#define pf printf
	inline ll read(){ll x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='0')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("subset.in","r",stdin);freopen("subset.out","w",stdout);}
	inline int min(int a,int b){return a<b?a:b;}inline int max(int a,int b){return a>b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int M=1e5+10;
	int n,m;ll f[M];
	std::vector<int>hv;
	inline short main(){
		file();
		n=read(),m=read();
		F(i,0,m)f[i]=read();
		F(i,1,m)if(f[i]){
			F(j,1,f[i])hv.push_back(i);
			int now=f[i];
			F(k,1,now)F(j,i,m)f[j]-=f[j-i];
		}
		for(auto x:hv)pi(x);
		return 0;
	}
}
signed main(){return EMT::main();}

2021-11-10 19:13:25 星期三

欢乐豆

只对被更改的点进行最短路松弛操作,每次跑一遍每个点只会被松弛一次,一共跑了m次,所以复杂度是正确的。每次跑最短路维护出来到其他没有被更改的点的最短距离。
复杂度\(O(m^2\log_m)\)

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
#include<queue>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("happybean.in","r",stdin);freopen("happybean.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline ll min(ll a,ll b){return a<b?a:b;}
	inline void pi(ll x){pf("%lld ",x);}inline void pn(){pf("\n");}
	const int N=1e5+10;const ll inf=1e18;
	struct node{int to,w;};std::vector<node>g[N];bool vis[N];
	int val[N],n,m,dfn[N],ti,time[N],fa[N];ll dis[N],ans;
	inline int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
	struct dp{int x,opt;ll dis;friend bool operator <(dp a,dp b){return a.dis>b.dis;}};
	std::priority_queue<dp>q;
	inline void change(int x,int v){
		if(fa[x]!=x)return;
		dis[x]=v;fa[x]=x+1;
		q.push({x,1,dis[x]+val[time[x]]});
		for(auto e:g[x])if(dis[e.to]>dis[x]+e.w){
			dis[e.to]=dis[x]+e.w;
			q.push({e.to,0,dis[e.to]});
		}
	}
	inline void dj(int s){
		F(i,1,ti)dis[i]=inf,fa[i]=i;dis[s]=0;fa[ti+1]=ti+1;
		q.push({s,0,0});
		while(!q.empty()){
			dp x=q.top();q.pop();
			if(x.opt){
				for(auto e:g[x.x])vis[e.to]=1;
				for(int i=1;i<=ti;i=find(i+1))
					if(!vis[i])change(i,x.dis);
				for(auto e:g[x.x])vis[e.to]=0;
			}else change(x.x,x.dis);
		}
	}
	inline short main(){
		file();
		n=read(),m=read();
		F(i,1,n)val[i]=read();
		F(i,1,m){
			int x=read(),y=read(),z=read();
			if(!dfn[x])time[dfn[x]=++ti]=x;
			if(!dfn[y])time[dfn[y]=++ti]=y;
			g[dfn[x]].push_back({dfn[y],z});
		}int key=0;
		F(i,1,n)if(!dfn[i]&&(!key||val[key]>val[i]))key=i;
		if(key)time[dfn[key]=++ti]=key;
		F(i,1,n)if(!dfn[i])ans+=1ll*val[i]*(n-1);
		F(i,1,ti){
			dj(i);ll mn=inf;
			F(j,1,ti)ans+=dis[j],mn=min(mn,dis[j]+val[time[j]]);
			ans+=mn*(n-ti);
		}pi(ans);
		return 0;
	}
}
signed main(){return EMT::main();}

超级加倍

建出两棵树,一棵的祖先权值小,另一棵大。从一棵里面求得dfs序,另一棵用树状数组维护即可。

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("charity.in","r",stdin);freopen("charity.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(ll x){pf("%lld ",x);}inline void pn(){pf("\n");}
	const int N=2e6+10;
	int head[N],co,fa[N],n,dfn[N],ti,last[N];
	struct node{int next,to;}e[N<<1];
	inline void add(int next,int to){e[++co]=(node){head[next],to},head[next]=co;}
	struct Bit{
		int t[N];
		inline void add(int x,int v){while(x<=n)t[x]+=v,x+=x&-x;}
		inline int ask(int x){int ans=0;while(x)ans+=t[x],x-=x&-x;return ans;}
		inline int ask(int l,int r){return ask(r)-ask(l-1);}
	}bit;
	struct tree{
		int head[N],co;
		struct node{int next,to;}e[N];
		inline void add(int next,int to){e[++co]=(node){head[next],to},head[next]=co;}
		inline void dfs(int k){dfn[k]=++ti;for(int i=head[k];i;i=e[i].next)dfs(e[i].to);last[k]=ti;}
	}t1;
	ll ans=0;
	struct tree2{
		int head[N],co;
		struct node{int next,to;}e[N];
		inline void add(int next,int to){e[++co]=(node){head[next],to},head[next]=co;}
		inline void dfs(int k){
			ans+=bit.ask(dfn[k],last[k]);
			bit.add(dfn[k],1);
			for(int i=head[k];i;i=e[i].next)dfs(e[i].to);
			bit.add(dfn[k],-1);
		}
	}t2;
	struct dsu{
		int fa[N];
		inline int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
		inline void init(){F(i,1,n)fa[i]=i;}
	}d1,d2;
	inline short main(){
		file();
		n=read();
		F(i,1,n){fa[i]=read();if(fa[i])add(fa[i],i),add(i,fa[i]);}
		d1.init();d2.init();
		D(I,n,1)
			for(int i=head[I];i;i=e[i].next)
				if(e[i].to>I){
					int fx=d1.find(I),fy=d1.find(e[i].to);
					t1.add(I,fy);d1.fa[fy]=fx;
				}
		F(I,1,n)
			for(int i=head[I];i;i=e[i].next)
				if(e[i].to<I){
					int fx=d2.find(I),fy=d2.find(e[i].to);
					t2.add(I,fy);d2.fa[fy]=fx;
				}
		t1.dfs(1);t2.dfs(n);
		pi(ans);
		return 0;
	}
}
signed main(){return EMT::main();}

叁仟柒佰万

发现对于一个点有贡献的点从左往右是单调的,于是开两个指针扫即可。

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define getchar getchar_unlocked
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("clods.in","r",stdin);freopen("clods.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int N=37001000,mod=1e9+7;
	int f[N],a[N],mex,n,vis[N],pre[N];bool hv[N];
	inline int ksm(int a,int b){
		int ans=1;
		while(b){
			if(b&1)ans=1ll*a*ans%mod;
			a=1ll*a*a%mod;b>>=1;
		}return ans;
	}
	inline short main(){
		file();
		int T=read();
		while(T--){
			n=read();mex=0;
			if(n!=37000000)memset(vis,0,sizeof(int)*(n+1));
			if(n!=37000000){
				F(i,1,n){
					a[i]=read();vis[a[i]]=1;
					while(vis[mex])mex++;
				}
			}else{
				int x=read(),y=read();a[1]=0;hv[0]=1;
				F(i,2,n){
					a[i]=(1ll*a[i-1]*x+y+i)&262143;
					hv[a[i]]=1;while(hv[mex])mex++;
				}
			}int cnt=0;
			if(n!=37000000)memset(vis,0,sizeof(int)*(mex+1));
			if(!mex){pi(ksm(2,n-1));pn();continue;}
			int key=1,now=-1;
			F(i,1,n){
				if(cnt==mex){now=i-1;break;}
				vis[a[i]]++;
				if(vis[a[i]]==1)cnt++;
			}
			if(n!=37000000)memset(pre,0,sizeof(int)*(n+1));
			pre[now]=f[now]=1;
			F(i,now+1,n){
				vis[a[i]]++;if(vis[a[i]]==1)cnt++;
				while(key<=i&&vis[a[key]]>1){
					vis[a[key]]--;key++;
				}
				if(key>0)f[i]=pre[key-1]+1;else f[i]=1;
				pre[i]=pre[i-1]+f[i],pre[i]-=pre[i]>=mod?mod:0;
			}pi(!f[n]?1:f[n]);pn();
		}
		return 0;
	}
}
signed main(){return EMT::main();}

开挂

从大往小枚举数,插到最靠近的空格里面即可。

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
const int Mxdt=100000; 
inline char gc(){
	static char buf[Mxdt],*p1=buf,*p2=buf;
	return p1==p2&&(p2=(p1=buf)+fread(buf,1,Mxdt,stdin),p1==p2)?EOF:*p1++;
}
inline int read(){
	int t=0,f=0;char v=gc();
	while(v<'0')f|=(v=='-'),v=gc();
	while(v>='0')t=(t<<3)+(t<<1)+v-48,v=gc();
	return f?-t:t;
}
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	typedef unsigned long long ull;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline void file(){freopen("openhook.in","r",stdin);freopen("openhook.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(ull x){pf("%llu ",x);}inline void pn(){pf("\n");}
	const int N=1e6+10,all=1001000000;
	int a[N],b[N],n,hv[N],rt;
	struct seg{
		int tot,ls[N*30],rs[N*30],val[N*30];
		inline void insert(int &p,int l,int r,int x){
			if(!p)p=++tot;
			if(l==r){val[p]=1;return;}
			int mid=(l+r)>>1;
			if(x<=mid)insert(ls[p],l,mid,x);else insert(rs[p],mid+1,r,x);
			val[p]=val[ls[p]]+val[rs[p]];
		}
		inline int find(int p,int l,int r,int ql,int qr){
			if(val[p]==r-l+1)return 0;if(!p)return l;
			if(l==r)return l;int mid=(l+r)>>1;
			if(ql>mid)return find(rs[p],mid+1,r,ql,qr);
			int x=find(ls[p],l,mid,ql,mid);if(x)return x;
			return find(rs[p],mid+1,r,mid+1,qr);
		}
	}segm;
	inline short main(){
		file();
		n=read();
		F(i,1,n)a[i]=read();std::sort(a+1,a+n+1);
		F(i,1,n)segm.insert(rt,1,a[n]+N,a[i]);
		F(i,1,n)b[i]=read();std::sort(b+1,b+n+1);
		D(i,n,1){
			if(a[i]!=a[i-1])continue;
			int x=segm.find(rt,1,a[n]+N,a[i],a[n]+N);
			hv[++hv[0]]=x-a[i];
			segm.insert(rt,1,a[n]+N,x);
		}std::sort(hv+1,hv+hv[0]+1,[](int i,int j){return i>j;});
		ull ans=0;
		F(i,1,hv[0])ans+=(ull)hv[i]*(ull)b[i];
		pi(ans);
		return 0;
	}
}
signed main(){return EMT::main();}

2021-11-05 19:59:30 星期五

校门外歪脖树上的鸽子

预处理方法比较笨,麻烦了一点,总之就是把每个点的左右儿子及相对区间处理好之后进行操作,
我们建立两颗线段树表示左儿子和右儿子管理自己兄弟节点的权值,修改和查询过程都是一样的,
都是先把\((l,l)\)\((r,r)\)节点拿出来,看自己作为左/右儿子最多跳到哪里,如果深度比两点lca小,
就只单点修改/查询自己到lca路上离lca最近的儿子,否则修改/查询上面所说的点(看自己作为左/右儿子最多跳到哪里),再树剖修改/查询上面点到自己到lca路上离lca最近的儿子的权值。

Code(7k警告)
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<map>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(int i=a;i<=b;i++)
	#define D(i,a,b) for(int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){auto it=freopen("pigeons.in","r",stdin);it=freopen("pigeons.out","w",stdout);it++;}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(ll x){pf("%lld ",x);}inline void pn(){pf("\n");}
	const int N=1e6+10;
	int n,m,in[N],fa[N],son[N][2],val[N],rt,rec[N],l[N],r[N];ll s[N];
	struct dp{int l,r;friend bool operator <(dp a,dp b){return a.l==b.l?a.r<b.r:a.l<b.l;}};std::map<dp,int>mp;
	inline void swap(int &x,int &y){x^=y^=x^=y;}
	inline void dfs1(int k){
		if(!k)return;
		val[k]=k;
		dfs1(son[k][1]),dfs1(son[k][0]);
		val[k]=min(val[k],min(val[son[k][1]],val[son[k][0]]));
	}
	inline void dfs2(int k){
		if(!k)return;
		rec[++rec[0]]=k;
		if(val[son[k][1]]<val[son[k][0]])dfs2(son[k][1]),dfs2(son[k][0]);
		else dfs2(son[k][0]),dfs2(son[k][1]);
	}
	inline void dfs3(int k){
		if(!k)return;
		if(r[son[k][0]]>l[son[k][1]])swap(son[k][0],son[k][1]);
		dfs3(son[k][0]),dfs3(son[k][1]);
	}
	inline void bfs(){
		static int q[N],hd,tl;hd=1;
		F(i,1,n)q[++tl]=i;
		while(hd<=tl){
			int x=q[hd++];
			if(!l[fa[x]])l[fa[x]]=l[x],r[fa[x]]=r[x];
			else{
				if(l[fa[x]]>r[x])l[fa[x]]=l[x];
				else r[fa[x]]=r[x];
			}in[fa[x]]--;
			if(!in[fa[x]])q[++tl]=fa[x];
		}dfs3(rt);
	}
	inline void change(int k,int ql,int qr,int d){
		if(l[k]>=ql&&r[k]<=qr){
			s[k]+=1ll*d*(r[k]-l[k]+1);
			return;
		}
		if(qr<=r[son[k][0]])change(son[k][0],ql,qr,d);
		else if(ql>r[son[k][0]])change(son[k][1],ql,qr,d);
		else change(son[k][0],ql,r[son[k][0]],d),change(son[k][1],l[son[k][1]],qr,d);
	}
	inline ll ask(int k,int ql,int qr){
		if(l[k]>=ql&&r[k]<=qr)return s[k];
		if(qr<=r[son[k][0]])return ask(son[k][0],ql,qr);
		if(ql>r[son[k][0]])return ask(son[k][1],ql,qr);
		return ask(son[k][0],ql,r[son[k][0]])+ask(son[k][1],l[son[k][1]],qr);
	}
	int dfn[N],top[N],ti,time[N],deep[N],siz[N],Son[N],jump[N][2],dy[N];
	inline int get(int x){
		return son[fa[x]][1]==x;
	}
	struct seg{
		ll lz[N<<2],sum[N<<2],val[N<<2];
		inline void build(int p,int l,int r,int kd){
			if(l==r){
				int x=time[l];
				if(get(x)!=kd)val[p]=EMT::r[son[fa[x]][get(x)^1]]-EMT::l[son[fa[x]][get(x)^1]]+1;
				return;
			}int mid=(l+r)>>1;
			build(p<<1,l,mid,kd),build(p<<1|1,mid+1,r,kd);
			val[p]=val[p<<1]+val[p<<1|1];
		}
		inline void down(int p){
			if(lz[p]){
				lz[p<<1]+=lz[p];
				lz[p<<1|1]+=lz[p];
				sum[p<<1]+=lz[p]*val[p<<1];
				sum[p<<1|1]+=lz[p]*val[p<<1|1];
				lz[p]=0;
			}
		}
		inline void change(int p,int l,int r,int ql,int qr,int v){
			if(l>=ql&&r<=qr){
				lz[p]+=v;
				sum[p]+=1ll*v*val[p];
				return;
			}int mid=(l+r)>>1;down(p);
			if(qr<=mid)change(p<<1,l,mid,ql,qr,v);
			else if(ql>mid)change(p<<1|1,mid+1,r,ql,qr,v);
			else change(p<<1,l,mid,ql,mid,v),change(p<<1|1,mid+1,r,mid+1,qr,v);
			sum[p]=sum[p<<1]+sum[p<<1|1];
		}
		inline ll ask(int p,int l,int r,int ql,int qr){
			if(l>=ql&&r<=qr)return sum[p];
			int mid=(l+r)>>1;down(p);
			if(qr<=mid)return ask(p<<1,l,mid,ql,qr);
			if(ql>mid)return ask(p<<1|1,mid+1,r,ql,qr);
			return ask(p<<1,l,mid,ql,mid)+ask(p<<1|1,mid+1,r,mid+1,qr);
		}
	}segm[2];
	struct awda{
		inline void dfs1(int k){
			if(!k)return;
			if(!fa[k])jump[k][0]=jump[k][1]=k;
			else{
				jump[k][0]=get(k)?k:jump[fa[k]][0];
				jump[k][1]=get(k)?jump[fa[k]][1]:k;
			}
			siz[k]=1;
			if(!son[k][0])return;
			deep[son[k][0]]=deep[son[k][1]]=deep[k]+1;
			dfs1(son[k][0]);dfs1(son[k][1]);
			siz[k]+=siz[son[k][0]],siz[k]+=siz[son[k][1]];
			Son[k]=siz[son[k][0]]>siz[son[k][1]]?son[k][0]:son[k][1];
		}
		inline void dfs2(int k,int tp){
			if(!k)return;
			time[dfn[k]=++ti]=k;top[k]=tp;
			if(!Son[k])return;
			dfs2(Son[k],tp);
			if(son[k][1]==Son[k])dfs2(son[k][0],son[k][0]);
			else dfs2(son[k][1],son[k][1]);
		}
		inline int getlca(int x,int y){
			while(top[x]!=top[y])if(deep[top[x]]<=deep[top[y]])y=fa[top[y]];else x=fa[top[x]];
			return deep[x]<deep[y]?x:y;
		}
		inline int getson(int x,int y){x=top[x];while(x!=top[y]){if(fa[x]==y)return x;x=top[fa[x]];}return Son[y];}
		inline void prepare(){
			dfs1(rt);dfs2(rt,rt);
		}
		inline void expand(){
			segm[0].build(1,1,n,1);segm[1].build(1,1,n,0);
		}
		inline void change(int x,int y,int v,int id){
			while(top[x]!=top[y])if(deep[top[x]]>=deep[top[y]])segm[id].change(1,1,n,dfn[top[x]],dfn[x],v),x=fa[top[x]];
			else segm[id].change(1,1,n,dfn[top[y]],dfn[y],v),y=fa[top[y]];
			if(x==y)return;
			if(deep[x]<=deep[y])segm[id].change(1,1,n,dfn[x]+1,dfn[y],v);
			else segm[id].change(1,1,n,dfn[y]+1,dfn[x],v);
		}
		inline ll ask(int x,int y,int id){
			ll ans=0;
			while(top[x]!=top[y])if(deep[top[x]]>=deep[top[y]])ans+=segm[id].ask(1,1,n,dfn[top[x]],dfn[x]),x=fa[top[x]];
			else ans+=segm[id].ask(1,1,n,dfn[top[y]],dfn[y]),y=fa[top[y]];
			if(x==y)return ans;
			if(deep[x]<=deep[y])ans+=segm[id].ask(1,1,n,dfn[x]+1,dfn[y]);
			else ans+=segm[id].ask(1,1,n,dfn[y]+1,dfn[x]);
			return ans;
		}
	}sp;
	inline void oneadd(int x,int v){
		if(x!=rt)x=son[fa[x]][get(x)^1];
		segm[get(x)].change(1,1,n,dfn[x],dfn[x],v);
	}
	inline ll oneask(int x){
		if(x!=rt)x=son[fa[x]][get(x)^1];
		return segm[get(x)].ask(1,1,n,dfn[x],dfn[x]);
	}
	inline void add(int l,int r,int v){
		int k=mp[{l,r}];
		if(k)oneadd(k,v);
		else{
			int x=dy[l],y=dy[r],xx=jump[x][0],yy=jump[y][1],lca=sp.getlca(x,y),sxn=sp.getson(x,lca),syn=sp.getson(y,lca);
			if(deep[xx]<=deep[lca])oneadd(sxn,v);
			else oneadd(xx,v),sp.change(xx,sxn,v,0);
			if(deep[yy]<=deep[lca])oneadd(syn,v);
			else oneadd(yy,v),sp.change(yy,syn,v,1);
		}
	}
	inline ll query(int l,int r){
		int k=mp[{l,r}];
		if(k)return oneask(k);
		else{
			int x=dy[l],y=dy[r],xx=jump[x][0],yy=jump[y][1],lca=sp.getlca(x,y),sxn=sp.getson(x,lca),syn=sp.getson(y,lca);
			ll ans=0;
			if(deep[xx]<=deep[lca])ans+=oneask(sxn);
			else ans+=oneask(xx),ans+=sp.ask(xx,sxn,0);
			if(deep[yy]<=deep[lca])ans+=oneask(syn);
			else ans+=oneask(yy),ans+=sp.ask(yy,syn,1);
			return ans;
		}
	}
	inline short main(){
		file();
		n=read(),m=read();
		F(i,n+1,2*n-1){
			son[i][0]=read(),son[i][1]=read();
			fa[son[i][0]]=fa[son[i][1]]=i;in[i]=2;
		}
		F(i,n+1,2*n-1)if(!fa[i]){rt=i;break;}
		dfs1(rt);dfs2(rt);int cnt=0;
		F(i,1,rec[0])if(rec[i]>=1&&rec[i]<=n)l[rec[i]]=r[rec[i]]=++cnt,dy[cnt]=rec[i];
		bfs();
		sp.prepare();n=2*n-1;sp.expand();
		F(i,1,n)mp[{l[i],r[i]}]=i;
		while(m--){
			int opt=read();
			if(opt==1){
				int l=read(),r=read(),d=read();
				add(l,r,d);
			}else{
				int l=read(),r=read();
				pi(query(l,r)),pn();
			}
		}
		return 0;
	}
}
signed main(){return EMT::main();}

混乱邪恶

先从小到大排序之后一加一减到最后,如果n是奇数就让第一个和第二个都是减,把相邻两项的差记录到vector中从大到小填补总差值即可

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(int i=a;i<=b;i++)
	#define D(i,a,b) for(int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){auto it=freopen("chaoticevil.in","r",stdin);it=freopen("chaoticevil.out","w",stdout);it++;}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int N=1e6+10;
	struct point{
		int id,val,ans;
		friend bool operator <(point a,point b){return a.val<b.val;}
	}p[N];
	int n,m;ll sum;
	std::vector<int>hv[N];
	inline short main(){
		file();
		puts("NP-Hard solved");
		n=read(),m=read();
		F(i,1,n)p[i].val=read(),p[i].id=i;
		std::sort(p+1,p+n+1);
		for(int i=1+(n&1);i<=n;i+=2){
			sum-=p[i].val,sum+=p[i+1].val;
			hv[p[i+1].val-p[i].val].push_back(i);
			p[i].ans=-1,p[i+1].ans=1;
		}if(n&1)p[1].ans=-1,sum-=p[1].val;
		D(i,m/3,1){
			if(!hv[i].size()||sum<i*2)continue;
			for(auto j:hv[i]){
				if(sum>=i*2)sum-=i*2,std::swap(p[j].ans,p[j+1].ans);
				else break;
			}
		}std::sort(p+1,p+n+1,[](point i,point j){return i.id<j.id;});
		F(i,1,n)pi(p[i].ans);
		return 0;
	}
}
signed main(){return EMT::main();}

快速排序

把nan的当做当前最大值之后stablesort即可

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(int i=a;i<=b;i++)
	#define D(i,a,b) for(int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){auto it=freopen("qsort.in","r",stdin);it=freopen("qsort.out","w",stdout);it++;}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int N=5e5+10;
	int n;
	struct num{bool isnan;int val;friend bool operator <(num a,num b){return a.val<b.val;}}p[N];
	inline short main(){
		file();
		int T=read();
		while(T--){
			n=read();int mx=0;
			F(i,1,n){
				p[i].val=p[i].isnan=0;
				char ch=getchar();
				while(ch!='n'&&!(ch>='0'&&ch<='9'))ch=getchar();
				if(ch=='n'){
					p[i].isnan=1;ch=getchar();
					while(ch!='n')ch=getchar();
					p[i].val=mx;
				}else{
					while(ch>='0'&&ch<='9')
						p[i].val=p[i].val*10+ch-'0',ch=getchar();
					mx=max(mx,p[i].val);
				}
			}
			std::stable_sort(p+1,p+n+1);
			F(i,1,n){
				if(p[i].isnan)pf("nan ");
				else pi(p[i].val);
			}pn();
		}
		return 0;
	}
}
signed main(){return EMT::main();}

回文

\(dp_{i,j,k}\)表示从左上角走到\((i,j)\),从右下角走到纵坐标为\(k\)有多少中方案匹配,由于只能向下向右走所以可以根据\(i,j,k\)算出来从右下角走到的横坐标\(l\)于是dp就是普通转移即可。

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(int i=a;i<=b;i++)
	#define D(i,a,b) for(int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){auto it=freopen("palin.in","r",stdin);it=freopen("palin.out","w",stdout);it++;}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int mod=993244853;
	int f[510][510][510];
	char s[510][510];
	int n,m;
	inline short main(){
		file();
		n=read(),m=read();
		F(i,1,n)scanf("%s",s[i]+1);
		if(s[1][1]!=s[n][m]){
			puts("0");
			return 0;
		}
		f[1][1][m]=1;
		F(i,1,n)F(j,1,m)D(k,m,1)if(f[i][j][k]){
			int step=i+j-2;
			if(step==(n+m-2)/2)break;
			int l=n+m-k-step;
			if(i<n&&l>1&&s[i+1][j]==s[l-1][k]){
				f[i+1][j][k]+=f[i][j][k],
				f[i+1][j][k]-=f[i+1][j][k]>=mod?mod:0;
			}
			if(i<n&&k>1&&s[i+1][j]==s[l][k-1]){
				f[i+1][j][k-1]+=f[i][j][k],
				f[i+1][j][k-1]-=f[i+1][j][k-1]>=mod?mod:0;
			}
			if(j<m&&l>1&&s[i][j+1]==s[l-1][k]){
				f[i][j+1][k]+=f[i][j][k],
				f[i][j+1][k]-=f[i][j+1][k]>=mod?mod:0;
			}
			if(j<m&&k>1&&s[i][j+1]==s[l][k-1]){
				f[i][j+1][k-1]+=f[i][j][k],
				f[i][j+1][k-1]-=f[i][j+1][k-1]>=mod?mod:0;
			}
		}
		int ans=0;
		if((n+m-2)&1){
			F(i,1,n)F(j,1,m)if(i+j-2==(n+m-2)/2){
				ans+=f[i][j][j],ans-=ans>=mod?mod:0,
				ans+=f[i][j][j+1],ans-=ans>=mod?mod:0;
			}
		}else{
			F(i,1,n)F(j,1,m)if(i+j-2==(n+m-2)/2)
				ans+=f[i][j][j],ans-=ans>=mod?mod:0;
		}
		pi(ans);
		return 0;
	}
}
signed main(){return EMT::main();}

2021-11-01 15:15:05 星期一

肯德基

发现答案就是

\[\sum\limits_{i=1}^{\sqrt{n}}\mu(i)i^2S(\left \lfloor \frac{n}{i^2} \right \rfloor) \]

其中\(S(i)=\sum\limits_{j=1}^{i}j\)
于是分块即可

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	typedef unsigned long long ull;
	#define pf printf
	#define F(i,a,b) for(int i=a;i<=b;i++)
	#define D(i,a,b) for(int i=a;i>=b;i--)
	inline ll read(){ll x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){auto it=freopen("kfc.in","r",stdin);it=freopen("kfc.out","w",stdout);it++;}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(ull x){pf("%llu ",x);}inline void pn(){pf("\n");}
	const int N=1e7+10;
	int mu[N],prime[N],co;ull pre[N];bool vis[N];
	inline void init(){
		mu[1]=1;
		F(i,2,10000000){
			if(!vis[i])prime[++co]=i,mu[i]=-1;
			F(j,1,co){
				if(prime[j]*i>=N)break;
				vis[prime[j]*i]=1;
				if(i%prime[j]==0)break;
				mu[i*prime[j]]=-mu[i];
			}
		}
		F(i,1,10000000)pre[i]=pre[i-1]+(ull)mu[i]*(ull)i*(ull)i;
	}
	ull ans;
	inline ull S(ull x){
		return x&1?(x+1)/2*x:x/2*(x+1);
	}
	inline short main(){
		file();
		init();
		int T=read();
		while(T--){
			ll n=read();ans=0;
			for(int l=1,r;l<=sqrt(n);l=r+1){
				r=sqrt(n/(n/l/l));
				ans+=(pre[r]-pre[l-1])*S(n/l/l);
			}pi(ans);pn();
		}
		return 0;
	}
}
signed main(){return EMT::main();}

技术情报局

对序列建立笛卡尔树。\(val_{i,0/1}\)表示以i管控区间的左/右端点为起点延伸到另一端的所有乘积的和,\(sum_i\)表示i管控区间的乘积,转移很好理解,累加到答案里就是左儿子的\(val_1\)和自己的\(val_0\),右儿子的\(val_0\)和自己的\(val_1\),自己这个点的加和

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	typedef unsigned int uint;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline uint read(){uint x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("tio.in","r",stdin);freopen("tio.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int N=1e7+10;
	int a[10000100];
	namespace GenHelper {
		unsigned z1, z2, z3, z4, b;
		inline unsigned rand_() {
			b = ((z1 << 6) ^ z1) >> 13;
			z1 = ((z1 & 4294967294U) << 18) ^ b;
			b = ((z2 << 2) ^ z2) >> 27;
			z2 = ((z2 & 4294967288U) << 2) ^ b;
			b = ((z3 << 13) ^ z3) >> 21;
			z3 = ((z3 & 4294967280U) << 7) ^ b;
			b = ((z4 << 3) ^ z4) >> 12;
			z4 = ((z4 & 4294967168U) << 13) ^ b;
			return (z1 ^ z2 ^ z3 ^ z4);
		}
	}
	inline void get (int n, unsigned s, int l, int r) {
		using namespace GenHelper;
		z1 = s;
		z2 = unsigned((~s) ^ 0x233333333U);
		z3 = unsigned(s ^ 0x1234598766U);
		z4 = (~s) + 51;
		for (int i = 1; i <= n; i ++) {
			int x = rand_() & 32767;
			int y = rand_() & 32767;
			a[i]=(l + (x * 32768 + y) % (r - l + 1));
		}
	}
	int n,l,r,mod,ls[N],rs[N],sta[N],top,ans,val[N][2],sum[N];uint s;
	inline void dfs(int k){
		ans+=1ll*a[k]*a[k]%mod;ans-=ans>=mod?mod:0;
		val[k][0]=val[k][1]=sum[k]=a[k];
		if(ls[k]){
			dfs(ls[k]);
			ans+=1ll*val[ls[k]][1]*a[k]%mod*a[k]%mod,ans-=ans>=mod?mod:0;
			val[k][0]=val[ls[k]][0],val[k][0]+=1ll*a[k]*sum[ls[k]]%mod,val[k][0]-=val[k][0]>=mod?mod:0;
			val[k][1]+=1ll*val[ls[k]][1]*a[k]%mod,val[k][1]-=val[k][1]>=mod?mod:0;
			sum[k]=1ll*sum[k]*sum[ls[k]]%mod;
		}
		if(rs[k]){
			dfs(rs[k]);
			ans+=1ll*val[rs[k]][0]*val[k][1]%mod*a[k]%mod,ans-=ans>=mod?mod:0;
			val[k][0]+=1ll*sum[k]*val[rs[k]][0]%mod,val[k][0]-=val[k][0]>=mod?mod:0;
			val[k][1]=1ll*val[k][1]*sum[rs[k]]%mod,val[k][1]+=val[rs[k]][1],val[k][1]-=val[k][1]>=mod?mod:0;
			sum[k]=1ll*sum[k]*sum[rs[k]]%mod;
		}
	}
	inline void build(){
		F(i,1,n){
			int k=top;
			while(k>0&&a[sta[k]]<a[i])k--;
			if(k)rs[sta[k]]=i;
			if(k<top)ls[i]=sta[k+1];
			sta[++k]=i;top=k;
		}dfs(sta[1]);
	}
	inline short main(){
		file();
		n=read(),s=read(),l=read(),r=read(),mod=read();
		get(n,s,l,r);
		build();pi(ans);
		return 0;
	}
}
signed main(){return EMT::main();}

聚烷撑乙二醇

倒着推期望,设\(f_i\)为i到n期望最大得到什么数,
于是与\(f_{i+1}\)相比较,当\(f_{i+1}\)完全小于\(l_{i}\)时直接就是自己的均值,
完全大于\(r_i\)时就是\(f_{i+1}\)
否则分答案在\(f_{i+1}\)以下与以上计算,以下的就取\(f_{i+1}\)否则取\(f_{i+1}\)\(r_i\)均值乘上概率即可

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef long double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(int i=a;i<=b;i++)
	#define D(i,a,b) for(int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){auto it=freopen("pag.in","r",stdin);it=freopen("pag.out","w",stdout);it++;}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(db x){pf("%.5Lf ",x);}inline void pn(){pf("\n");}
	const int N=1e6+10;
	int l[N],r[N],n;
	db f[N];
	inline short main(){
		file();
		n=read();
		F(i,1,n)l[i]=read(),r[i]=read();
		f[n]=(l[n]+r[n])/2.0;
		D(i,n-1,1){
			if(r[i]<=f[i+1])f[i]=f[i+1];
			else if(l[i]>=f[i+1])f[i]=(l[i]+r[i])/2.0;
			else f[i]=(f[i+1]-l[i])/(r[i]-l[i])*f[i+1]+(r[i]+f[i+1])/2.0*(r[i]-f[i+1])/(r[i]-l[i]);
		}pi(f[1]);
		return 0;
	}
}
signed main(){return EMT::main();}

集合均值

被卡常了...由于期望线性性,于是可以把概率乘上贡献均摊到每一个数上,相加即可

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("mos.in","r",stdin);freopen("mos.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int mod=998244353;
	const int N=2e7+10;
	int n,m,inv[N],suf[N];
	inline short main(){
		file();
		n=read(),m=read();
		inv[0]=inv[1]=1;
		F(i,2,n*m+1)inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
		D(i,n*m+1,1)suf[i]=inv[i],suf[i]+=suf[i+1],suf[i]-=suf[i]>=mod?mod:0;
		int pre=1,ans=0,A=0;
		F(i,1,n*m){
			ans+=1ll*pre*inv[n*m-i+1]%mod*suf[i+1]%mod,ans-=ans>=mod?mod:0;
			pre=1ll*pre*(mod+1-inv[n*m-i+1])%mod;
		}
		F(i,1,n)A+=1ll*m*read()%mod,A-=A>=mod?mod:0;
		pi(1ll*A*ans%mod);
		return 0;
	}
}
signed main(){return EMT::main();}

2021-10-31 07:18:18 星期日

乘法

将答案奇偶分治
发现答案就是

\[\sum\limits_{i=1}^{\left \lfloor \frac{(n-1)}{2} \right \rfloor} (2i+1) \]

由于对\(2^{64}\)取模于是最多选63个。

\(f_{i,j}\)表示从i个数里选j个数乘起来所有方案的总和。于是有:

\[f_{i,j}=f_{i-1,j}+nf_{i-1,j-1} \]

如果固定j,发现这是个2j次的多项式,于是可以插值
预处理出前300*300项f数组之后插值即可

插值时无法直接使用逆元,于是直接把分子分母中的2拿出来再求逆元即可

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	typedef unsigned long long ull;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline ull read(){ull x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("multiplication.in","r",stdin);freopen("multiplication.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	ull f[500][500],mp[500],bin[50000];
	inline void init(){int n=300;F(i,0,n)f[i][0]=1;F(i,1,n)F(j,1,i)f[i][j]=i*f[i-1][j-1]+f[i-1][j];bin[0]=1;F(i,1,30000)bin[i]=bin[i-1]<<1;}
	inline ll calc2(ll &x){ll ans=__builtin_ctzll(x);x>>=ans;return ans;}
	ull inv(ull x){if(mp[x])return mp[x];ll b=(1ull<<63)-1;ull ans=1;int st=x;while(b){if(b&1)ans*=x;x*=x;b>>=1;}return mp[st]=ans;}
	inline ull S(ll s,int k){
		ull ans=0;
		F(i,k,3*k){
			ull sum=f[i][k];ll cnt2=0;bool f=1;
			F(j,k,3*k){
				if(i==j)continue;
				ll up=s-j,down=i-j;
				if(up<=0)up=-up,f=!f;
				if(down<=0)down=-down,f=!f;
				cnt2+=calc2(up);cnt2-=calc2(down);
				sum*=up,sum*=inv(down);
			}if(!sum)continue;
			sum*=bin[cnt2];
			if(!f)ans-=sum;
			else ans+=sum;
		}return ans;
	}
	inline ull solve(ull n){
		if(!n)return 1;ull A=1;
		ull ans=0;
		while(n){
			ans=0;
			F(i,0,63)ans+=S((n-1)/2,i)<<i;
			A*=ans;n/=2;
		}return A;
	}
	inline void print(ull x){
		if(!x)return;
		print(x/16);
		int now=x%16;
		if(now<10)pf("%d",now);
		else pf("%c",now-10+'A');
	}
	inline short main(){
		file();	
		init();
		int T=read();
		while(T--){
			ull x=read();ull st=x,cnt2=0;
			while(st)cnt2+=st/2,st>>=1;
			cnt2%=4;
			printf("%llX",solve(x)<<cnt2),pn();
		}
		return 0;
	}
}
signed main(){return EMT::main();}

矩阵

可以进行记忆化搜索,但是答案要对1取max(wssb)

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<map>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("matrix.in","r",stdin);freopen("matrix.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	int n,m,a[50000],ans;
	inline int id(int x,int y){
		if(n<m)return x-1+(y-1)*n;else return (x-1)*m+y-1;
	}
	struct dp{int id,val;friend bool operator <(dp a,dp b){return a.id==b.id?a.val<b.val:a.id<b.id;}};
	std::map<dp,int>mp;
	inline void die(){puts("-1");exit(0);}
	inline int dfs(int x,int y,int bei){
		int Z=mp[{id(x,y),bei}];if(Z)return Z;
		int val=1;
		if(x>1&&a[id(x,y)]*bei==a[id(x-1,y)])val=max(val,dfs(x-1,y,bei)+1);
		if(x<n&&a[id(x,y)]*bei==a[id(x+1,y)])val=max(val,dfs(x+1,y,bei)+1);
		if(y>1&&a[id(x,y)]*bei==a[id(x,y-1)])val=max(val,dfs(x,y-1,bei)+1);
		if(y<m&&a[id(x,y)]*bei==a[id(x,y+1)])val=max(val,dfs(x,y+1,bei)+1);
		mp[{id(x,y),bei}]=val;return val;
	}
	inline short main(){
		file();
		n=read(),m=read();
		F(i,1,n)F(j,1,m)a[id(i,j)]=read();
		F(i,1,n)F(j,1,m){
			if(i<n)
				if(a[id(i+1,j)]==a[id(i,j)])die();
			if(j<m)
				if(a[id(i,j+1)]==a[id(i,j)])die();
		}
		F(i,1,n)F(j,1,m)if(a[id(i,j)]){
			if(i>1)
				if(a[id(i-1,j)]%a[id(i,j)]==0)ans=max(ans,dfs(i,j,a[id(i-1,j)]/a[id(i,j)]));
			if(j>1)
				if(a[id(i,j-1)]%a[id(i,j)]==0)ans=max(ans,dfs(i,j,a[id(i,j-1)]/a[id(i,j)]));
			if(i<n)
				if(a[id(i+1,j)]%a[id(i,j)]==0)ans=max(ans,dfs(i,j,a[id(i+1,j)]/a[id(i,j)]));
			if(j<m)
				if(a[id(i,j+1)]%a[id(i,j)]==0)ans=max(ans,dfs(i,j,a[id(i,j+1)]/a[id(i,j)]));
		}pi(max(ans,1));
		return 0;
	}
}
signed main(){return EMT::main();}

特殊字符串

比较笨的做法。
\(f_{i,j}\)表示以i结尾上个字符是j的最大答案,于是就有转移:

\[f_{i,j}=\max\limits_{k<i}{f_{k,l}+w_{l,c_k}} \]

其中\(w_{i,j}\)表示第一个字符为i第二个为j的贡献
于是使用树状数组或线段树转移即可

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("shiki.in","r",stdin);freopen("shiki.out","w",stdout);}
	inline ll max(ll a,ll b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(ll x){pf("%lld ",x);}inline void pn(){pf("\n");}
	const int N=1e5+10;
	ll w[20000];int n,m;ll ans;
	char s[N];ll t[26][N];
	inline void change(int x,ll v,int id){while(x<=n)t[id][x]=max(t[id][x],v),x+=x&-x;}
	inline ll ask(int x,int id){ll ans=-1e18;while(x)ans=max(ans,t[id][x]),x-=x&-x;return ans;}
	inline short main(){
		file();
		n=read();
		scanf("%s",s+1);
		m=read();
		F(i,1,m){
			char ch1=getchar();
			while(ch1<'a'||ch1>'z')ch1=getchar();
			char ch2=getchar();
			while(ch2<'a'||ch2>'z')ch2=getchar();
			w[(int)ch1*131+(int)ch2]+=read();
		}
		memset(t,-0x3f,sizeof(t));
		F(i,1,n){
			ll maxn=0;
			F(j,0,25){
				ll val=ask(i,j);
				val+=w[(j+'a')*131+s[i]];
				maxn=max(maxn,val);
			}
			change(i+1,maxn,s[i]-'a');
			ans=max(ans,maxn);
		}
		pi(ans);
		return 0;
	}
}
signed main(){return EMT::main();}

宝可梦

由于题目中说道一个点到另一个点有且只有一条简单路径,所以可以随便找一个合法点从那里开始模拟走一遍求得到点\((i,j)\)且朝向为\(goal\)时的最小步数,询问时直接对四种朝向取min即可。

Code
#include <cstring>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
namespace EMT {
typedef long long ll;
typedef double db;  //(double)clock() / (double)CLOCKS_PER_SEC;
#define pf printf
#define F(i, a, b) for (register int i = a; i <= b; i++)
#define D(i, a, b) for (register int i = a; i >= b; i--)
inline int read() {
    int x = 0, f = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9') {
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar();
    return x * f;
}
inline void file() {
    freopen("pokemon.in", "r", stdin);
    freopen("pokemon.out", "w", stdout);
}
inline int max(int a, int b) { return a > b ? a : b; }
inline int min(int a, int b) { return a < b ? a : b; }
inline void pi(int x) { pf("%d ", x); }
inline void pn() { pf("\n"); }
int n, m, Q, pre[600000][5], stp;
bool a[600000];
inline int id(int x, int y) {
    if (n < m)
        return x - 1 + (y - 1) * n;
    else
        return (x - 1) * m + y - 1;
}
inline void bfs(int x, int y, int goal) {
    while (1) {
        if (pre[id(x, y)][goal] != -1)
            return;
        stp++;
        pre[id(x, y)][goal] = stp;
        if (goal == 1) {
            if (y < m && a[id(x, y + 1)])
                y++, goal = 4;
            else if (x > 1 && a[id(x - 1, y)])
                x--;
            else if (y > 1 && a[id(x, y - 1)])
                y--, goal = 3;
            else
                x++, goal = 2;
        } else if (goal == 2) {
            if (y > 1 && a[id(x, y - 1)])
                y--, goal = 3;
            else if (x < n && a[id(x + 1, y)])
                x++;
            else if (y < m && a[id(x, y + 1)])
                y++, goal = 4;
            else
                x--, goal = 1;
        } else if (goal == 3) {
            if (x > 1 && a[id(x - 1, y)])
                x--, goal = 1;
            else if (y > 1 && a[id(x, y - 1)])
                y--;
            else if (x < n && a[id(x + 1, y)])
                x++, goal = 2;
            else
                y++, goal = 4;
        } else {
            if (x < n && a[id(x + 1, y)])
                x++, goal = 2;
            else if (y < m && a[id(x, y + 1)])
                y++;
            else if (x > 1 && a[id(x - 1, y)])
                x--, goal = 1;
            else
                y--, goal = 3;
        }
    }
}
inline int getans(int x, int y, int gx, int gy, int goal) {
    int ans = 1e9;
    F(i, 1, 4) if (pre[id(gx, gy)][i] != -1) {
        if (pre[id(gx, gy)][i] >= pre[id(x, y)][goal])
            ans = min(ans, pre[id(gx, gy)][i] - pre[id(x, y)][goal]);
        else
            ans = min(ans, pre[id(gx, gy)][i] - pre[id(x, y)][goal] + stp - 1);
    }
    return ans;
}
inline short main() {
    file();
    n = read(), m = read();
    memset(pre, -1, sizeof(pre));
    F(i, 1, n) F(j, 1, m) {
        char ch = getchar();
        while (ch != '.' && ch != 'X') ch = getchar();
        a[id(i, j)] = ch == '.' ? 1 : 0;
    }
    bool fl = 1;
    F(i, 1, n) {
        F(j, 1, m) if (a[id(i, j)]) {
            if (i > 1 && a[id(i - 1, j)])
                bfs(i, j, 1);
            else if (i < n && a[id(i + 1, j)])
                bfs(i, j, 2);
            else if (j > 1 && a[id(i, j - 1)])
                bfs(i, j, 3);
            else
                bfs(i, j, 4);
            fl = 0;
            break;
        }
        if (!fl)
            break;
    }
    Q = read();
    while (Q--) {
        int x = read(), y = read(), gx = read(), gy = read(), ans = 1, goal;
        char ch = getchar();
        while (ch != 'U' && ch != 'D' && ch != 'L' && ch != 'R') ch = getchar();
        goal = (ch == 'U' ? 1 : (ch == 'D' ? 2 : (ch == 'L' ? 3 : 4)));
        if (x == gx && y == gy) {
            puts("0");
            continue;
        }
        if (goal == 1)
            x--;
        if (goal == 2)
            x++;
        if (goal == 3)
            y--;
        if (goal == 4)
            y++;
        ans = getans(x, y, gx, gy, goal) + 1;
        pi(ans);
        pn();
    }
    return 0;
}
}  // namespace EMT
signed main() { return EMT::main(); }

2021-10-29 19:35:52 星期五

七负我

随机化草过即可

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<ctime>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("nanami.in","r",stdin);freopen("nanami.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	int p[50],n,m,x;ll zt[45];
	inline short main(){
		file();
		n=read();m=read(),x=read();
		F(i,1,m){
			int x=read(),y=read();
			zt[x]|=1ll<<(y-1);
			zt[y]|=1ll<<(x-1);
		}
		F(i,1,n)p[i]=i;int ans=0;
		while(clock()<=6000){
			std::random_shuffle(p+1,p+n+1);
			ll need=0;int siz=0;
			F(i,1,n)if((need&zt[p[i]])==need){
				need|=(1ll<<(p[i]-1));
				siz++;
			}ans=max(ans,siz);
		}db one=(db)x/(db)ans;
		pf("%.6lf",one*one*ans*(ans-1)/2);
		return 0;
	}
}
signed main(){return EMT::main();}

团不过

\(p_i\)表示i堆石子的方案数为\((2^n-1)^{\tfrac{i}{}}\),\(f_i\)表示i堆石子不满足的方案数答案就是\(p_n-f_n\)
考虑前i-1堆石子中有i-2堆异或起来是0最后一堆不是,于是再加上一堆和这堆石子相等的但是这是不合法的于是减去,
还有前i-1堆已经是0了新加一组肯定不是0于是减去于是:

\[f_i=p_{i-1}-f_{i-1}-(i-1)(2^n-i+1)f_{i-2} \]

于是就可以递推了

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("yui.in","r",stdin);freopen("yui.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int N=1e7+10,mod=1e9+7;
	int p[N],f[N],n;
	inline int ksm(int a,int b){
		int ans=1;
		while(b){
			if(b&1)ans=1ll*a*ans%mod;
			a=1ll*a*a%mod,b>>=1;
		}return ans;
	}
	inline short main(){
		file();
		n=read();
		int p2n=ksm(2,n);int st=p2n-1;
		p[1]=st,p[2]=1ll*st*(st-1)%mod;
		F(i,3,n){
			p[i]=1ll*p[i-1]*(st-i+1)%mod;p[i]+=p[i]<0?mod:0;
			f[i]=p[i-1],f[i]-=f[i-1],f[i]+=f[i]<0?mod:0;
			f[i]-=1ll*(i-1)*(p2n-i+1)%mod*f[i-2]%mod,f[i]+=f[i]<0?mod:0,f[i]-=f[i]>=mod?mod:0;
		}pi((p[n]-f[n]+mod)%mod);
		return 0;
	}
}
signed main(){return EMT::main();}

尽梨了

假做法切了IEE...其实hack数据我自己都拍出来了...
a从大往小排b从小往大排之后滚动数组dp即可

Code

#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cassert>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(int i=a;i<=b;i++)
	#define D(i,a,b) for(int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("eriri.in","r",stdin);freopen("eriri.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int N=210000;
	int f[2][N],n,T,a[N],b[N],ans;bool vis[N];
	struct point{int a,b;friend bool operator <(point a,point b){return a.a==b.a?a.b<b.b:a.a>b.a;}}p[N];
	inline void dfs(int now,int cnt,int time){
        if(time<=T){
            if(ans<cnt){
                ans=cnt;
            }
        }else return;
        if(cnt==n)return;
        F(i,1,n)if(!vis[i]){
            if(time+1+1ll*a[i]*(time+1)+b[i]>T)continue;
            vis[i]=1;
            dfs(i+1,cnt+1,time+1+a[i]*(time+1)+b[i]);
            vis[i]=0;
        }
    }
	inline void solve1(){
		F(i,1,n)a[i]=read(),b[i]=read();
        dfs(1,0,0);
        pi(ans);
	}
	inline short main(){
		file();
		srand(time(0));
		n=read(),T=read();
		if(n<=10){solve1();return 0;}
		memset(f,0x3f,sizeof(f));
		f[0][0]=0;
		F(i,1,n)p[i].a=read(),p[i].b=read();
		std::sort(p+1,p+n+1);
		F(i,0,n-1){
			int now=i&1,to=now^1;
			F(j,0,i)
				if(f[now][j]<=T){
					f[to][j]=min(f[to][j],f[now][j]);
					ll x=1ll*p[i+1].a*(f[now][j]+1)+p[i+1].b+f[now][j]+1;
					if(x<=T)f[to][j+1]=min(f[to][j+1],x);
					f[now][j]=0x3f3f3f3f;
				}else break;
		}
		D(i,n,0)if(f[n&1][i]<=T){pi(i);return 0;}
		return 0;
	}
}
signed main(){return EMT::main();}

莓良心

考虑到w并不影响一个数对答案的贡献次数于是可以对w求和用斯特林数求出每个数对的贡献最后的式子就长这样:

\[ans=\sum w_i \times (\left \{ ^n_k\right \}+(n-1)\left \{ ^{n-1}_{k} \right \}) \]

其中斯特林数可以利用容斥预处理次方线性求解

Code

#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("ichigo.in","r",stdin);freopen("ichigo.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int mod=998244353,N=1e6+10;
	inline int ksm(int a,int b){
		int ans=1;
		while(b){
			if(b&1)ans=1ll*a*ans%mod;
			a=1ll*a*a%mod;b>>=1;
		}return ans;
	}
	int pw[N],n,prime[N],co,k,jc[N],inv[N],w[N],pw2[N];bool vis[N];
	inline int C(int n,int m){return 1ll*jc[n]*inv[m]%mod*inv[n-m]%mod;}
	inline int stl1(int n,int k){
		int now=0;
		F(i,0,k)now+=(i&1?-1ll:1ll)*C(k,i)*pw[k-i]%mod,now-=now>=mod?mod:0,now+=now<0?mod:0;
		return 1ll*inv[k]*now%mod;
	}
	inline int stl2(int n,int k){
		int now=0;
		F(i,0,k)now+=(i&1?-1ll:1ll)*C(k,i)*pw2[k-i]%mod,now-=now>=mod?mod:0,now+=now<0?mod:0;
		return 1ll*inv[k]*now%mod;
	}
	inline void init(){
		F(i,2,n){
			if(!vis[i])prime[++co]=i,pw[i]=ksm(i,n),pw2[i]=ksm(i,n-1);
			F(j,1,co){
				if(prime[j]*i>n)break;
				vis[prime[j]*i]=1;
				pw[prime[j]*i]=1ll*pw[i]*pw[prime[j]]%mod;
				pw2[prime[j]*i]=1ll*pw2[i]*pw2[prime[j]]%mod;
				if(i%prime[j]==0)break;
			}
		}
		jc[0]=inv[1]=inv[0]=1;
		F(i,1,n)jc[i]=1ll*jc[i-1]*i%mod;
		F(i,2,n)inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
		F(i,1,n)inv[i]=1ll*inv[i]*inv[i-1]%mod;
	}
	inline short main(){
		file();
		pw[1]=pw2[1]=1;
		n=read();init();k=read();
		F(i,1,n)w[i]=read();
		int ans=0;
		F(i,1,n)ans+=w[i],ans-=ans>=mod?mod:0;
		ans=1ll*ans*((stl1(n,k)+1ll*(n-1)*stl2(n-1,k)%mod)%mod)%mod;
		pi(ans);
		return 0;
	}
}
signed main(){return EMT::main();}

2021-10-19 15:06:35 星期二
鸽子来更更了

滑稽树下你和我

把边转化成点,用两个人的位置作为状态跑最短路,求路径上最长的那条边即可。
调了半天发现传参把double变成int了,wssb

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("tree.in","r",stdin);freopen("tree.out","w",stdout);}
	inline db max(db a,db b){return a>b?a:b;}inline db min(db a,db b){return a<b?a:b;}
	inline void pi(db x){pf("%.10lf ",x);}inline void pn(){pf("\n");}
	const int N=2100;const db eps=1e-6;
	db d[N][N],dis[N][N];bool vis[N][N];
	int n,stx,sty,head[N],co,in[N];
	struct point{int x,y;}p[N];
	inline db getdis(db x,db y,db a,db b){return sqrt((db)(x-a)*(x-a)+(db)(y-b)*(y-b));}
	struct dp{int x,y;db dis;friend bool operator <(dp a,dp b){return a.dis>b.dis;}};
	std::priority_queue<dp>q;
	struct bian{int x1,y1,x2,y2;db k,b;int from,to;}edge[N];
	struct node{int next,to;}e[N*N];
	inline void add(int next,int to){e[++co]=(node){head[next],to},head[next]=co;}
	inline db getdis2(int i,int j){
		db k=-1.0/edge[j].k,b=(db)p[i].y-p[i].x*k;
		db x=(edge[j].b-b)/(k-edge[j].k),y=edge[j].k*x+edge[j].b;
		if((x>=edge[j].x1&&x<=edge[j].x2)||(x>=edge[j].x2&&x<=edge[j].x1))return getdis(p[i].x,p[i].y,x,y);
		else return min(d[i][edge[j].from],d[i][edge[j].to]);
	}
	inline void spfa(){
		F(i,1,n*2)F(j,1,n*2)dis[i][j]=1e9;
		dis[stx][sty]=d[stx][sty];
		q.push((dp){stx,sty,dis[stx][sty]});
		while(!q.empty()){
			dp x=q.top();q.pop();
			if(vis[x.x][x.y])continue;
			vis[x.x][x.y]=1;
			for(register int i=head[x.x],j=e[i].to;i;i=e[i].next,j=e[i].to)if(dis[j][x.y]>max(dis[x.x][x.y],d[j][x.y])){
				dis[j][x.y]=max(dis[x.x][x.y],d[j][x.y]);
				q.push((dp){j,x.y,dis[j][x.y]});
			}
			for(register int i=head[x.y],j=e[i].to;i;i=e[i].next,j=e[i].to)if(dis[x.x][j]>max(dis[x.x][x.y],d[x.x][j])){
				dis[x.x][j]=max(dis[x.x][x.y],d[x.x][j]);
				q.push((dp){x.x,j,dis[x.x][j]});
			}
		}
	}
	inline short main(){
		file();
		n=read(),stx=read(),sty=read();
		F(i,1,n)p[i].x=read(),p[i].y=read();
		F(i,1,n)F(j,i+1,n)d[i][j]=d[j][i]=getdis(p[i].x,p[i].y,p[j].x,p[j].y);
		F(i,1,n-1){
			int x=read(),y=read();
			add(x,i+n),add(i+n,x),add(y,i+n),add(i+n,y);
			in[x]++;in[y]++;
			edge[i]=(bian){p[x].x,p[x].y,p[y].x,p[y].y,0,0,x,y};
			edge[i].k=(db)(p[y].y-p[x].y)/(db)(p[y].x-p[x].x);
			edge[i].b=p[y].y-p[y].x*edge[i].k;
		}
		F(i,1,n)F(j,n+1,n*2-1)d[i][j]=d[j][i]=getdis2(i,j-n);//pf("%d %d %.10lf\n",i,j,d[i][j]);
		spfa();db ans=1e9;
		F(i,1,n)if(in[i]==1)F(j,1,n)if(in[j]==1)ans=min(ans,dis[i][j]);
		pi(ans);
		return 0;
	}
}
signed main(){return EMT::main();}

光线追踪

光追好评
粗暴的将double斜率作为下标进行动态开点线段树标记永久化取min即可。

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("raytracing.in","r",stdin);freopen("raytracing.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}inline void pd(db x){pf("%lf ",x);}
	const int N=1e5+10;const db eps=1e-6;
	int tot,rt1,rt2;
	struct dp{int val,id;friend bool operator <(dp a,dp b){return a.val==b.val?a.id>b.id:a.val<b.val;}};
	struct seg{
		int ls[N*60],rs[N*60],val[N*60],id[N*60];
		inline void change(int &p,db l,db r,db ql,db qr,int v,int Id){
			// pd(l);pd(r);pd(ql);pd(qr);pi(v);pi(Id);pn();
			if(!p)p=++tot;
			if((l>=ql&&r<=qr)||(r-l<=eps)){
				if(val[p]>=v){
					val[p]=v;id[p]=Id;
				}else if(!val[p])val[p]=v,id[p]=Id;
				return;
			}db mid=(l+r)/2.0;
			if(qr<=mid)change(ls[p],l,mid,ql,qr,v,Id);
			else if(ql>mid)change(rs[p],mid,r,ql,qr,v,Id);
			else change(ls[p],l,mid,ql,mid,v,Id),change(rs[p],mid,r,mid,qr,v,Id);
		}
		inline dp ask(int p,db l,db r,db x){
			if(!p)return {1000000000,0};
			if(r-l<=eps)return {val[p],id[p]};
			db mid=(l+r)/2.0;dp z=(dp){val[p],id[p]};
			if(x<=mid){
				dp y=ask(ls[p],l,mid,x);
				if(!z.val)return y;
				if(!y.val)return z;
				if(z<y)return z;else return y;
			}else{
				dp y=ask(rs[p],mid,r,x);
				if(!z.val)return y;
				if(!y.val)return z;
				if(z<y)return z;else return y;
			}
		}
	}segm1,segm2;
	inline short main(){
		file();
		int T=read();int i=0;
		while(T--){
			int opt=read();i++;
			if(opt==1){
				int x1=read(),y1=read(),x2=read(),y2=read();
				if(x1==x2||y1==y2)continue;
				if(!x1){
					db k=(db)y1/(db)x2;
					segm1.change(rt1,0,1e9,k,1e9,y1,i);
				}else if(!y1){
					db k=(db)y2/(db)x1;
					segm2.change(rt2,0,1e9,0,k,x1,i);
				}else{
					db k1=(db)y1/(db)x1,k2=(db)y2/(db)x1,k3=(db)y1/(db)x2;
					segm1.change(rt1,0,1e9,k3,k1,y1,i);
					segm2.change(rt2,0,1e9,k1,k2,x1,i);
				}
			}else{
				int x=read(),y=read();db k;if(x!=0)k=(db)y/(db)x;else k=1e9;
				dp v1=segm1.ask(rt1,0,1e9,k),v2=segm2.ask(rt2,0,1e9,k);
				if(!v1.val){
					pi(v2.id);pn();
				}else if(!v2.val){
					pi(v1.id);pn();
				}else{
					if(fabs(v1.val-(db)v2.val*k)<=eps){pi(max(v1.id,v2.id)),pn();continue;}
					if(v1.val<(db)v2.val*k)pi(v1.id);
					else if(v1.val>v2.val*k)pi(v2.id);
					else pi(max(v1.id,v2.id));
					pn();
				}
			}
		}
		return 0;
	}
}
signed main(){return EMT::main();}

邻面合并

在这里以一个1表示从这个1开始到下一个1的矩形,于是就可以进行状压了。



#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("merging.in","r",stdin);freopen("merging.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	struct dp{int l,r;};
	int n,m,in[110],a[110][10],base[110],f[110][1<<8];
	std::vector<dp>hv[110][1<<8];
	std::vector<int>able[110];
	inline void pt(int x){
		int s[10];
		F(i,1,m)if(x&(1<<(i-1)))s[i]=1;else s[i]=0;
		F(i,1,m)pf("%d",s[i]);pf(" ");
	}
	inline short main(){
		file();
		n=read(),m=read();
		F(i,1,n)F(j,1,m)a[i][j]=read(),in[i]|=(a[i][j]<<(j-1));
		F(i,1,n){
			int l=1,r;
			while(l<=m){
				while(!a[i][l]&&l<=m)l++;
				if(l>m)break;r=l;
				while(a[i][r+1]&&r+1<=m)r++;
				base[i]|=(1<<(l-1));l=r+1;
			}
			F(j,1,(1<<m)-1)
				if((j|in[i])==in[i]&&(j&base[i])==base[i]){
					able[i].push_back(j);
					l=1;
					while(l<=m){
						while(!(j&(1<<(l-1)))&&l<=m)l++;
						if(l>m)break;r=l;
						while(!(j&(1<<r))&&r+1<=m&&a[i][r+1])r++;
						hv[i][j].push_back((dp){l,r});l=r+1;
					}
				}
			if(!able[i].size())able[i].push_back(0);
		}able[0].push_back(0);
		memset(f,0x3f,sizeof(f));
		f[0][0]=0; 
		F(i,1,n)
			for(auto j:able[i])
				for(auto k:able[i-1]){
					int now=hv[i][j].size();
					int key1=0,key2=0;
					while(key1<hv[i][j].size()&&key2<hv[i-1][k].size()){
						dp x=hv[i][j][key1],y=hv[i-1][k][key2];
						if(x.l==y.l&&x.r==y.r)now--,key1++,key2++;
						else if(x.l<y.l)key1++;
						else if(x.l>y.l)key2++;
						else key1++,key2++;
					}
					f[i][j]=min(f[i][j],f[i-1][k]+now);
				}
		int ans=1e9;
		for(auto i:able[n])ans=min(ans,f[n][i]);
		pi(ans);
		return 0;
	}
}
signed main(){return EMT::main();}

2021-10-15 11:59:15 星期五

特立独行的图

我们将值域锁定到[-1e9,1e9],当这里没有0时,负数只能和正数成边,正数也只能和负数成边,于是可以二分图考虑,另外当i<j并且都是正数时,i的连边集合肯定被j包含,负数反之,于是判断一下连边集合,当有0时就判一下有几个三元环bitset实现即可。

Code


#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<bitset>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	/*char buf[1<<20], *p1, *p2;
	char gc() { return p1 == p2 ? p2 = buf + fread(p1 = buf, 1, 1<<20, stdin), (p1 == p2) ? EOF : *p1++ : *p1++; }
	inline int read(int f = 1, char c = gc(), int x = 0) {
		while(c < '0' || c > '9') f = (c == '-') ? -1 : 1, c = gc();
		while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = gc();
		return f * x;
	}*/
	inline void file(){freopen("graph.in","r",stdin);freopen("graph.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int N=1100,inf=1e9;
	int in[N],n,m,head[N],col[N],co,ans[N],p[N],cnt,A,B,C;
	std::bitset<N>hv[N];bool fl;
	struct node{int next,to;}e[N*N];
	inline void add(int next,int to){e[++co]=(node){head[next],to},head[next]=co;}
	inline bool com(int i,int j){return in[i]<in[j];}
	inline void swap(int &a,int &b){int c=a;a=b;b=c;}
	inline void dfs(int k,int c){
		col[k]=c;if(!fl)return;
		for(register int i=head[k];i;i=e[i].next)if(!col[e[i].to])dfs(e[i].to,c^1);else if(col[k]==col[e[i].to])fl=0;
	}
	inline short main(){
		file();
		int T=read();int waa=0;
		while(T--){
			F(i,1,n)in[i]=head[i]=col[i]=ans[i]=0,hv[i].reset();cnt=co=0;
			n=read(),m=read();
			F(i,1,m){
				int x=read(),y=read();
				add(x,y),add(y,x);
				in[x]++,in[y]++;
				hv[x][y]=hv[y][x]=1;
			}
			F(i,1,n)
				for(register int j=head[i];j;j=e[j].next)
					if(e[j].to>i&&(hv[i]&hv[e[j].to]).any()){
						// for(register int k=head[e[j].to];k;k=e[k].next)
							// if(e[k].to>e[j].to&&hv[i][e[k].to]){
								// col[i]=col[e[j].to]=col[e[k].to]=1;
								// goto X;
							// }
						F(k,1,n)if(hv[i][k]&&hv[e[j].to][k]){
							col[k]=col[e[j].to]=col[i]=1;
							goto X;
						}
					}
			X:;
			int tot=0;A=0,B=0,C=0;
			F(i,1,n)if(col[i])tot++,A=B,B=C,C=i;
			if(tot>3){pf("No\n");continue;}
			if(tot){
				if(in[A]==2)swap(C,A);
				else if(in[B]==2)swap(C,B);
				else if(in[C]!=2){
					pf("No\n");
					continue;
				}
			}col[A]=col[B]=0;
			fl=1;
			F(i,1,n)if(!col[i])dfs(i,2);
			if(!fl){pf("No\n");continue;}
			F(i,1,n)if(col[i]==2)p[++cnt]=i;
			if(tot){
				int maxn=0;
				for(register int i=head[A];i;i=e[i].next)
					maxn=max(maxn,col[e[i].to]);
				if(maxn<=2)swap(A,B);
				for(register int i=head[A];i;i=e[i].next)if(col[e[i].to]==2){fl=0;break;}
				if(!fl){pf("No\n");continue;}
				for(register int i=head[B];i;i=e[i].next)if(col[e[i].to]==3){fl=0;break;}
				if(!fl){pf("No\n");continue;}
				if(in[A]!=n-cnt||in[B]!=cnt+1){
					pf("No\n");
					continue;
				}ans[B]=-inf;
			}
			std::sort(p+1,p+cnt+1,com);
			F(i,1,cnt-1)if((hv[p[i]]|hv[p[i+1]])!=hv[p[i+1]]){
				fl=0;break;
			}if(!fl){pf("No\n");continue;}
			int now=0;
			F(i,1,cnt){
				for(register int j=head[p[i]];j;j=e[j].next)if(!ans[e[j].to])
					++now,ans[e[j].to]=now-inf;
				ans[p[i]]=++now;
			}ans[A]=inf;ans[C]=0;
			pf("Yes\n2000000000 ");
			F(i,1,n)pi(ans[i]);pn();
		}
		return 0;
	}
}
signed main(){return EMT::main();}

2021-10-14 20:46:58 星期四

骆驼

这么water的构造为啥考场上没想出来啊
由于n是5的倍数,于是把\(n\times n\)的大矩形分成若干个\(5\times 5\)的小矩形,分n是5的奇倍数和偶倍数讨论。

n等于5的奇数倍数时路线如下:

否则如下:

发现每个矩形内的路径最多只有八种,于是打表打出来即可。

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("camel.in","r",stdin);freopen("camel.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	int n;
	int base[10][10][10],ans[1100][1100],now;
	inline void add(int x,int y,int id){
		F(i,x,x+4)F(j,y,y+4)ans[i][j]=now+base[id][i-x+1][j-y+1];
		now+=base[id][0][0];
	}
	inline void solve1(){
		add(1,1,1);
		int x=1,y=1;
		while(x+10<=n-4)x+=5,add(x,y,2);
		x+=5,add(x,y,3);
		while(y+10<=n-4)y+=5,add(x,y,3);
		y+=5,add(x,y,4);
		x-=5;
		bool fl=1;
		while(x>=11){
			if(fl){
				while(y-5>=6)add(x,y,5),y-=5;
				add(x,y,4);
			}else{
				while(y+5<=n-4)add(x,y,3),y+=5;
				add(x,y,4);
			}x-=5;
			fl^=1;
		}
		fl=1;
		while(y>=11){
			if(fl)add(x,y,4),x-=5,add(x,y,5),y-=5;
			else add(x,y,6),x+=5,add(x,y,5),y-=5;
			fl^=1;
		}
		add(x,y,6),x+=5,add(x,y,7);
		ans[4][4]=now+1;
		ans[1][4]=now+2;
	}
	inline void solve2(){
		int x=1,y=1;
		add(x,y,8);
		while(x+10<=n-4)x+=5,add(x,y,2);
		x+=5,add(x,y,3);
		while(y+10<=n-4)y+=5,add(x,y,3);
		y+=5,add(x,y,4);
		x-=5;bool fl=1;
		while(x>=6){
			if(fl){
				while(y-5>=6)add(x,y,5),y-=5;
				add(x,y,4);
			}else{
				while(y+5<=n-4)add(x,y,3),y+=5;
				add(x,y,4);
			}x-=5,fl^=1;
		}
		while(y-5>=1)add(x,y,5),y-=5;
		ans[3][3]=now+1;
	}
	inline short main(){
		file();
		n=read();
		if(n==5){
			pf("1 13 21 18 12 \n6 16 24 9 4 \n22 19 2 14 20 \n25 10 5 17 11 \n7 15 23 8 3 ");
			return 0;
		}
		base[1][0][0]=23;
		base[1][1][1]=    1 ;base[1][1][2]=   15 ;base[1][1][3]=   12 ;base[1][1][4]=   0  ;base[1][1][5]=    5 ;
		base[1][2][1]=   18 ;base[1][2][2]=    9 ;base[1][2][3]=    3 ;base[1][2][4]=   17 ;base[1][2][5]=   10 ;
		base[1][3][1]=   13 ;base[1][3][2]=   21 ;base[1][3][3]=    6 ;base[1][3][4]=   14 ;base[1][3][5]=   22 ;
		base[1][4][1]=    2 ;base[1][4][2]=   16 ;base[1][4][3]=   11 ;base[1][4][4]=   0  ;base[1][4][5]=    4 ;
		base[1][5][1]=   19 ;base[1][5][2]=    8 ;base[1][5][3]=   23 ;base[1][5][4]=   20 ;base[1][5][5]=    7 ;
		base[2][0][0]=25;
		base[2][1][1]=   14 ;base[2][1][2]=   19 ;base[2][1][3]=    5 ;base[2][1][4]=   13 ;base[2][1][5]=   18 ;
		base[2][2][1]=    3 ;base[2][2][2]=   11 ;base[2][2][3]=   16 ;base[2][2][4]=   21 ;base[2][2][5]=   10 ;
		base[2][3][1]=    6 ;base[2][3][2]=   23 ;base[2][3][3]=    1 ;base[2][3][4]=    7 ;base[2][3][5]=   24 ;
		base[2][4][1]=   15 ;base[2][4][2]=   20 ;base[2][4][3]=    4 ;base[2][4][4]=   12 ;base[2][4][5]=   17 ;
		base[2][5][1]=    2 ;base[2][5][2]=    8 ;base[2][5][3]=   25 ;base[2][5][4]=   22 ;base[2][5][5]=    9 ;
		base[3][0][0]=25;
		base[3][1][1]=   16 ;base[3][1][2]=    8 ;base[3][1][3]=   24 ;base[3][1][4]=   15 ;base[3][1][5]=    2 ;
		base[3][2][1]=   11 ;base[3][2][2]=   19 ;base[3][2][3]=    4 ;base[3][2][4]=   10 ;base[3][2][5]=   22 ;
		base[3][3][1]=    6 ;base[3][3][2]=   14 ;base[3][3][3]=    1 ;base[3][3][4]=    7 ;base[3][3][5]=   25 ;
		base[3][4][1]=   17 ;base[3][4][2]=    9 ;base[3][4][3]=   23 ;base[3][4][4]=   18 ;base[3][4][5]=    3 ;
		base[3][5][1]=   12 ;base[3][5][2]=   20 ;base[3][5][3]=    5 ;base[3][5][4]=   13 ;base[3][5][5]=   21 ;
		base[4][0][0]=25;
		base[4][1][1]=    2 ;base[4][1][2]=   22 ;base[4][1][3]=   25 ;base[4][1][4]=    3 ;base[4][1][5]=   21 ;
		base[4][2][1]=   15 ;base[4][2][2]=   10 ;base[4][2][3]=    7 ;base[4][2][4]=   18 ;base[4][2][5]=   13 ;
		base[4][3][1]=   24 ;base[4][3][2]=    4 ;base[4][3][3]=    1 ;base[4][3][4]=   23 ;base[4][3][5]=    5 ;
		base[4][4][1]=    8 ;base[4][4][2]=   19 ;base[4][4][3]=   14 ;base[4][4][4]=    9 ;base[4][4][5]=   20 ;
		base[4][5][1]=   16 ;base[4][5][2]=   11 ;base[4][5][3]=    6 ;base[4][5][4]=   17 ;base[4][5][5]=   12 ;
		base[5][0][0]=25;
		base[5][1][1]=    9 ;base[5][1][2]=   17 ;base[5][1][3]=   24 ;base[5][1][4]=   10 ;base[5][1][5]=   18 ;
		base[5][2][1]=   22 ;base[5][2][2]=   12 ;base[5][2][3]=    7 ;base[5][2][4]=   21 ;base[5][2][5]=   13 ;
		base[5][3][1]=   25 ;base[5][3][2]=    4 ;base[5][3][3]=    1 ;base[5][3][4]=   16 ;base[5][3][5]=    5 ;
		base[5][4][1]=    8 ;base[5][4][2]=   20 ;base[5][4][3]=   23 ;base[5][4][4]=   11 ;base[5][4][5]=   19 ;
		base[5][5][1]=    2 ;base[5][5][2]=   15 ;base[5][5][3]=    6 ;base[5][5][4]=    3 ;base[5][5][5]=   14 ;
		base[6][0][0]=25;
		base[6][1][1]=    6 ;base[6][1][2]=   22 ;base[6][1][3]=   14 ;base[6][1][4]=    7 ;base[6][1][5]=    2 ;
		base[6][2][1]=   19 ;base[6][2][2]=    9 ;base[6][2][3]=    4 ;base[6][2][4]=   20 ;base[6][2][5]=   12 ;
		base[6][3][1]=   24 ;base[6][3][2]=   16 ;base[6][3][3]=    1 ;base[6][3][4]=   23 ;base[6][3][5]=   15 ;
		base[6][4][1]=    5 ;base[6][4][2]=   21 ;base[6][4][3]=   13 ;base[6][4][4]=    8 ;base[6][4][5]=    3 ;
		base[6][5][1]=   18 ;base[6][5][2]=   10 ;base[6][5][3]=   25 ;base[6][5][4]=   17 ;base[6][5][5]=   11 ;
		base[7][0][0]=25;
		base[7][1][1]=   25 ;base[7][1][2]=   12 ;base[7][1][3]=   20 ;base[7][1][4]=   17 ;base[7][1][5]=   11 ;
		base[7][2][1]=    5 ;base[7][2][2]=   15 ;base[7][2][3]=   23 ;base[7][2][4]=    8 ;base[7][2][5]=    3 ;
		base[7][3][1]=   21 ;base[7][3][2]=   18 ;base[7][3][3]=    1 ;base[7][3][4]=   13 ;base[7][3][5]=   19 ;
		base[7][4][1]=   24 ;base[7][4][2]=    9 ;base[7][4][3]=    4 ;base[7][4][4]=   16 ;base[7][4][5]=   10 ;
		base[7][5][1]=    6 ;base[7][5][2]=   14 ;base[7][5][3]=   22 ;base[7][5][4]=    7 ;base[7][5][5]=    2 ;
		base[8][0][0]=24;
		base[8][1][1]=    1 ;base[8][1][2]=    6 ;base[8][1][3]=   13 ;base[8][1][4]=   21 ;base[8][1][5]=    5 ;
		base[8][2][1]=   11 ;base[8][2][2]=   19 ;base[8][2][3]=    3 ;base[8][2][4]=    8 ;base[8][2][5]=   18 ;
		base[8][3][1]=   14 ;base[8][3][2]=   22 ;base[8][3][3]=    0 ;base[8][3][4]=   15 ;base[8][3][5]=   23 ;
		base[8][4][1]=    2 ;base[8][4][2]=    7 ;base[8][4][3]=   12 ;base[8][4][4]=   20 ;base[8][4][5]=    4 ;
		base[8][5][1]=   10 ;base[8][5][2]=   16 ;base[8][5][3]=   24 ;base[8][5][4]=    9 ;base[8][5][5]=   17 ;
		if((n/5)&1)solve1();else solve2();
		F(i,1,n){F(j,1,n)pi(ans[i][j]);pn();}
		return 0;
	}
}
signed main(){return EMT::main();}

玩游戏

发现前50pts可以nk求解,\(E(n)=\sum\limits_{i=1}^{n}\frac{1}{i}\),剩下的就是不会的导数了,抄个柿子走人了(

Code


#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using std::cin;using std::cout;
namespace EMT{
	typedef long long ll;typedef long double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("game.in","r",stdin);freopen("game.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	ll n;int k;double pre[52][1000100];db h1,h2;
	inline short main(){
		file();
		cout.unsetf(std::ios::fixed);
		cout.setf(std::ios::scientific);
		cout.precision(9);
		cin>>k>>n;
		if(n<=1000000){
			F(i,1,n)pre[0][i]=pre[0][i-1]+1.0/(db)i;
			F(i,1,k)F(j,1,n)
				pre[i][j]=pre[i][j-1]+pre[i-1][j];
			cout<<pre[k][n];
			return 0;
		}else{
			F(i,1,k)h1+=1.0/(db)i;
			h2=log(n)/log(2.718281828)+0.5772156649+1.0/(db)(2*n);
			db nk=1,bs=1;
			F(i,1,k)nk*=n,bs*=i;
			cout<<nk/bs*(h2-h1)*0.9999999999;
		}
		return 0;
	}
}
signed main(){return EMT::main();}

洛希极限

发现转移的话横纵坐标单调不减,于是考虑单调队列
预处理出每个点前一行最前哪一列能转移到自己,记为\(down_{i,j}\),用相反意义的\(up_{i,j}\)辅助记录。left同理。
通过这两个数组维护队列内的点来转移自己,另外开一个转移的桶记录方案总数,如果转移出现重复减去即可。

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("roche.in","r",stdin);freopen("roche.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int mod=1e9+7;
	const int N=2100;
	int down[N][N],up[N][N],left[N][N],right[N][N],tong[N],n,m,q;
	inline int getright(int x,int y){return !right[x][y]?x:right[x][y]=getright(right[x][y],y);}
	inline int getup(int x,int y){return !up[x][y]?y:up[x][y]=getup(x,up[x][y]);}
	struct dp{
		int len,val;
		friend bool operator <(dp a,dp b){return a.len<b.len;}
		friend dp operator +(dp a,dp b){
			dp c;
			if(a<b)c=b;else if(b<a)c=a;else	c.len=a.len,c.val=a.val+b.val,c.val-=c.val>=mod?mod:0;
			return c;
		}
	}f[N][N];
	struct queue{
		int hd,tl,cnt[N],w[N];
		dp q[N];
		inline void init(){
			hd=1,tl=0;
			F(i,1,max(n,m))cnt[i]=0;
		}
		inline void push(int x,dp v){
			while(hd<=tl&&q[tl]<v){
				cnt[q[tl].len]-=q[tl].val,
				cnt[q[tl].len]+=cnt[q[tl].len]<0?mod:0;
				tl--;
			}q[++tl]=v;
			cnt[v.len]+=v.val,cnt[v.len]-=cnt[v.len]>=mod?mod:0;
			w[tl]=x;
		}
		inline dp query(int y){
			while(hd<=tl&&w[hd]<y){
				cnt[q[hd].len]-=q[hd].val,
				cnt[q[hd].len]+=cnt[q[hd].len]<0?mod:0;
				hd++;
			}return (dp){q[hd].len+1,cnt[q[hd].len]};
		}
	}q1[N],q2[N];
	struct martix{
		int r1,c1,r2,c2;
	}r[500100],rr[500100];
	inline short main(){
		file();
		int T=read();
		while(T--){
			n=read(),m=read(),q=read();F(i,1,n)q1[i].init();F(i,1,m)q2[i].init();
			F(i,1,q)rr[i].r1=read(),rr[i].c1=read(),rr[i].r2=read(),rr[i].c2=read();
			F(i,1,n)tong[i]=0;
			F(i,1,q)tong[rr[i].r1]++;
			F(i,1,n)tong[i]+=tong[i-1];
			F(i,1,q)r[tong[rr[i].r1]--]=rr[i];
			F(i,1,n+1)F(j,1,m+1)up[i][j]=down[i][j]=left[i][j]=right[i][j]=0;
			F(i,1,q)F(y,r[i].c1+1,r[i].c2)for(int x=r[i].r1+1;x<=r[i].r2;)if(!right[x][y]){
				right[x][y]=x+1;left[x][y]=r[i].r1;x++;
			}else x=getright(x,y);
			F(i,1,n)F(j,1,m)f[i][j].len=f[i][j].val=1;
			F(i,1,m)tong[i]=0;
			F(i,1,q)tong[rr[i].c1]++;
			F(i,1,m)tong[i]+=tong[i-1];
			F(i,1,q)r[tong[rr[i].c1]--]=rr[i];
			F(i,1,q)F(x,r[i].r1+1,r[i].r2)for(int y=r[i].c1+1;y<=r[i].c2;)if(!up[x][y]){
				up[x][y]=y+1;down[x][y]=r[i].c1;y++;
			}else y=getup(x,y);
			F(i,1,n)F(j,1,m){
				q1[i].push(j,f[i][j]),
				q2[j].push(i,f[i][j]);
				if(i+1<=n&&j+1<=m&&down[i+1][j+1]){
					f[i+1][j+1]=f[i+1][j+1]+q1[i].query(down[i+1][j+1]),
					f[i+1][j+1]=f[i+1][j+1]+q2[j].query(left[i+1][j+1]);
					if(f[i][j].len+1==f[i+1][j+1].len)f[i+1][j+1].val-=f[i][j].val,f[i+1][j+1].val+=f[i+1][j+1].val<0?mod:0;
				}
			}dp ans;ans.len=ans.val=0;
			F(i,1,n)F(j,1,m)ans=ans+f[i][j];
			pi(ans.len),pi(ans.val),pn();
		}
		return 0;
	}
}
signed main(){return EMT::main();}

2021-10-11 19:47:52 星期一

Sanrd

爆码200行发现T了,分数还没爆搜高,弃疗了,贴个80pts跑路...

Code


%: pragma GCC optimize(2)
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("sanrd.in","r",stdin);freopen("sanrd.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int N=5e5+10;
	int n,a[N];bool vis[N];
	int rec1[N],co1,rec2[N],co2;
	int val=0,val2=0;
	struct get{
		struct dp{int val,x;}t[N],f[N];
		inline void clear(){F(i,1,n)t[i].val=t[i].x=0;}
		inline void add(int x,int v,int id){
			while(x){if(t[x].val<v)t[x].val=v,t[x].x=id;x-=x&-x;}
		}
		inline dp ask(int x){
			dp ans={0,0};
			while(x<=n){if(t[x].val>ans.val)ans=t[x];x+=x&-x;}
			return ans;
		}
		inline void print(){
			pi(co1);pn();
			D(i,co1,1)pi(rec1[i]);pn();
			F(i,1,n)if(!vis[i]&&f[i].val==val2){
				int now=i;
				while(now)rec2[++co2]=now,now=f[now].x;
				pi(co2);pn();
				D(i,co2,1)pi(rec2[i]);pn();
				exit(0);
			}
		}
		inline int getans(int x){
			clear();int ans=0;
			F(i,1,n)if(!vis[i]){
				dp w=ask(a[i]);
				f[i]=w;ans=max(ans,f[i].val);
				add(a[i],w.val+1,i);
			}val2=max(val2,ans);
			if(x==1)return 0;
			else if(ans<val2)return 0;
			else{
				print();
			}
		}
	}t2;
	struct tre{int val;
	std::vector<int>x;inline void unique(){std::sort(x.begin(),x.end()),std::unique(x.begin(),x.end());}}t[N],dp[N];
	inline void change(int x,int v,int v2){
		while(x<=n){
			if(t[x].val<v){
				t[x].x.clear();
				t[x].x.push_back(v2);
				t[x].val=v;
			}else if(t[x].val==v){
				t[x].x.push_back(v2);
			}x+=x&-x;
		}
	}
	inline tre ask(int x){
		tre ans;ans.val=0;
		while(x){
			if(t[x].val>ans.val){
				ans=t[x];
			}else if(t[x].val==ans.val){
				for(auto i:t[x].x)
					ans.x.push_back(i);
			}x-=x&-x;
		}return ans;
	}
	inline void check(){
		t2.getans(0);
	}
	inline void dfs(int k,int st){
		vis[k]=1;rec1[++co1]=k;
		if(!dp[k].x.size()){
			check();
			vis[k]=0;co1--;
			return;
		}
		for(auto i:dp[k].x)
			dfs(i,st);
		vis[k]=0;co1--;
	}
	inline short main(){
		file();
		n=read();
		F(i,1,n)a[i]=read();t2.getans(1);
		F(i,1,n){
			tre x=ask(a[i]);
			dp[i]=x;
			dp[i].unique();
			change(a[i],x.val+1,i);
		}
		F(i,1,n)val=max(val,dp[i].val);
		F(i,1,n)if(dp[i].val==val)dfs(i,i);
		puts("-1");
		return 0;
	}
}
signed main(){return EMT::main();}

游戏

矩阵sb快速幂,柿子很好吃。

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("game.in","r",stdin);freopen("game.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	int n,p,q,aw,bw,a[5][5],b[5][5],c[5][5],d[5],e[5];
	const int mod=1e9+7;
	inline int ksm(int a,int b){int ans=1;while(b){if(b&1)ans=1ll*a*ans%mod;a=1ll*a*a%mod,b>>=1;}return ans;}
	inline void mul(int d[5],int a[5][5]){
		memset(e,0,sizeof(e));
		F(i,1,2)F(j,1,2)e[i]+=1ll*d[j]*a[j][i]%mod,e[i]-=e[i]>=mod?mod:0;
		F(i,1,2)d[i]=e[i];
	}
	inline void muls(int a[5][5]){
		memset(c,0,sizeof(c));
		F(i,1,2)F(k,1,2)F(j,1,2)c[i][j]+=1ll*a[i][k]*a[k][j]%mod,c[i][j]-=c[i][j]>=mod?mod:0;
		F(i,1,2)F(j,1,2)a[i][j]=c[i][j];
	}
	inline void mul(int a[5][5],int b[5][5]){
		memset(c,0,sizeof(c));
		F(i,1,2)F(k,1,2)F(j,1,2)c[i][j]+=1ll*a[i][k]*b[k][j]%mod,c[i][j]-=c[i][j]>=mod?mod:0;
		F(i,1,2)F(j,1,2)a[i][j]=c[i][j];
	}
	inline short main(){
		file();
		int inv=ksm(100000000,mod-2);
		int T=read(),inv1,inv2;
		while(T--){
			n=read(),p=1ll*read()*inv%mod,q=1ll*read()*inv%mod;
			int bs=1ll*(1-p+mod)*(1-q+mod)%mod,bs2=mod+1-1ll*p*q%mod;
			inv1=ksm(mod+1-bs,mod-2),inv2=ksm(bs2,mod-2),aw=1ll*p*inv1%mod,bw=1-aw+mod;
			a[1][1]=1ll*((p-1ll*p*q%mod)%mod+mod)%mod*inv2%mod,
			a[1][2]=1ll*(1-q+mod)*inv2%mod,
			a[2][1]=1ll*(1-p+mod)*inv2%mod,
			a[2][2]=(1ll*(q-1ll*p*q%mod)%mod+mod)%mod*inv2%mod,
			b[1][1]=1ll*((q-1ll*p*q%mod)%mod+mod)%mod*inv1%mod,
			b[1][2]=1ll*q*inv1%mod;
			b[2][1]=1ll*p*inv1%mod,
			b[2][2]=1ll*((p-1ll*p*q%mod)%mod+mod)%mod*inv1%mod,
			d[1]=aw,d[2]=bw;
			mul(a,b);
			int x=n/2;
			while(x){
				if(x&1)mul(d,a);
				muls(a);x>>=1;
			}
			a[1][1]=1ll*((p-1ll*p*q%mod)%mod+mod)%mod*inv2%mod,
			a[1][2]=1ll*(1-q+mod)*inv2%mod,
			a[2][1]=1ll*(1-p+mod)*inv2%mod,
			a[2][2]=(1ll*(q-1ll*p*q%mod)%mod+mod)%mod*inv2%mod;
			b[1][1]=1ll*((q-1ll*p*q%mod)%mod+mod)%mod*inv1%mod,
			b[1][2]=1ll*q*inv1%mod;
			b[2][1]=1ll*p*inv1%mod,
			b[2][2]=1ll*((p-1ll*p*q%mod)%mod+mod)%mod*inv1%mod;
			if(n&1)mul(d,b);
			pi(d[1]);pn();
		}
		return 0;
	}
}
signed main(){return EMT::main();}

钱仓

暴力找哪个点能成为断点更新答案即可。

Code



#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
#include<cassert>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("barn.in","r",stdin);freopen("barn.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline ll min(ll a,ll b){return a<b?a:b;}
	inline void pi(ll x){pf("%lld ",x);}inline void pn(){pf("\n");}
	const int N=1e5+10;
	std::vector<int>hv;
	int n,a[N<<1],s[N<<1];ll pre[N],rans=1e18;
	inline short main(){
		file();
		n=read();
		F(i,1,n){
			a[i]=a[i+n]=s[i]=s[i+n]=read();
			pre[i]=pre[i-1]+1ll*i*i;
		}
		F(i,1,n)if(!a[i]&&a[i+1])hv.push_back(i);
		for(auto k:hv){
			int st=k+1,ed=k+n;
			int last=ed;bool fl=1;ll ans=0;
			D(i,ed,st){
				if(!a[i])continue;
				if(last-i+1<a[i]){fl=0;break;}	
				int x=last-a[i]+1;
				if(x!=i)ans+=pre[last-i]-pre[x-i-1];
				else ans+=pre[last-i];
				last=x-1;
			}if(fl)rans=min(rans,ans);
		}pi(rans);
		return 0;
	}
}
signed main(){return EMT::main();}

自然数

线段树维护区间最大值,求和以及区间覆盖,考虑删除i对答案的贡献即可

Code


#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("mex.in","r",stdin);freopen("mex.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(ll x){pf("%lld ",x);}inline void pn(){pf("\n");}
	const int N=2e5+10;
	int mex[N],n,a[N],vis[N],last[N],llast[N];ll ans;
	struct seg{
		int val[N<<2],lz[N<<2];ll sum[N<<2];
		inline void up(int p){
			sum[p]=sum[p<<1]+sum[p<<1|1];
			val[p]=max(val[p<<1],val[p<<1|1]);
		}
		inline void build(int p=1,int l=1,int r=n){
			lz[p]=-1;
			if(l==r){
				val[p]=sum[p]=mex[l];
				return;
			}int mid=(l+r)>>1;
			build(p<<1,l,mid),build(p<<1|1,mid+1,r);
			up(p);
		}
		inline void down(int p,int l,int r){
			if(lz[p]!=-1){
				int mid=(l+r)>>1;
				lz[p<<1]=lz[p<<1|1]=lz[p];
				val[p<<1]=val[p<<1|1]=lz[p];
				sum[p<<1]=1ll*(mid-l+1)*lz[p];
				sum[p<<1|1]=1ll*(r-mid)*lz[p];
				lz[p]=-1;
			}
		}
		inline void change(int p,int l,int r,int ql,int qr,int v){
			if(l>=ql&&r<=qr){
				sum[p]=1ll*(r-l+1)*v;
				val[p]=lz[p]=v;
				return;
			}int mid=(l+r)>>1;down(p,l,r);
			if(qr<=mid)change(p<<1,l,mid,ql,qr,v);
			else if(ql>mid)change(p<<1|1,mid+1,r,ql,qr,v);
			else change(p<<1,l,mid,ql,mid,v),change(p<<1|1,mid+1,r,mid+1,qr,v);
			up(p);
		}
		inline int find(int p,int l,int r,int v){
			if(l==r)return val[p]>=v?l:l+1;
			int mid=(l+r)>>1;down(p,l,r);
			if(val[p<<1]<v)return find(p<<1|1,mid+1,r,v);
			else return find(p<<1,l,mid,v);
		}
		inline ll getsum(int p,int l,int r,int ql,int qr){
			if(l>=ql&&r<=qr)return sum[p];
			int mid=(l+r)>>1;
			if(qr<=mid)return getsum(p<<1,l,mid,ql,qr);
			if(ql>mid)return getsum(p<<1|1,mid+1,r,ql,qr);
			return getsum(p<<1,l,mid,ql,mid)+getsum(p<<1|1,mid+1,r,mid+1,qr);
		}
	}segm;
	inline short main(){
		file();
		n=read();
		F(i,1,n)a[i]=read();
		int key=0;
		F(i,1,n){
			if(a[i]<=n)vis[a[i]]++;
			while(vis[key])key++;
			mex[i]=key;
		}
		D(i,n,1){
			if(a[i]>n){last[i]=n+1;continue;}
			last[i]=llast[a[i]];
			if(!last[i])last[i]=n+1;
			llast[a[i]]=i;
		}
		segm.build();
		F(i,1,n){
			ans+=segm.sum[1];
			if(a[i]>n){
				segm.change(1,1,n,1,i,0);
				continue;
			}
			int x=segm.find(1,1,n,a[i]);
			if(x!=n+1&&x<=last[i]-1)segm.change(1,1,n,x,last[i]-1,a[i]);
			segm.change(1,1,n,1,i,0);
		}pi(ans);
		return 0;
	}
}
signed main(){return EMT::main();}

2021-10-10 14:59:30 星期日
T2矩阵快速幂考试结束前半个小时才想到,wssb.果然还是wtcl

小L的有向图

状压dp,一个点对一个集合的贡献是这个点未连向这个集合的其他出边度数作为指数的二次方乘积,预处理出每个集合里有几个一即可。

Code


#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("topology.in","r",stdin);freopen("topology.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int mod=998244353;
	int f[1<<22],n,count[1<<22],m,head[25],out[25],bin[650],num[25];
	inline int Count(int x){
		int ans=0;
		while(x)ans++,x-=x&-x;
		return ans;
	}
	inline short main(){
		file();
		n=read(),m=read();
		F(i,1,m){
			int x=read(),y=read();
			out[x]|=(1<<(y-1));
			num[x]++;
		}
		f[0]=1;
		bin[0]=1;
		F(i,1,m)bin[i]=bin[i-1]<<1,bin[i]-=bin[i]>=mod?mod:0;
		F(i,0,(1<<n)-1)count[i]=Count(i);
		F(i,0,(1<<n)-1)F(j,1,n)if(!(i&(1<<(j-1)))){
			int to=i|(1<<(j-1));
			f[to]+=1ll*f[i]*bin[num[j]-count[i&out[j]]]%mod,
			f[to]-=f[to]>=mod?mod:0;
		}
		pi(f[(1<<n)-1]);
		return 0;
	}
}
signed main(){return EMT::main();}

连边

将所有黑点丢进去跑最短路,最后累加答案,所有白点连接的最短的最短路边

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("minimum.in","r",stdin);freopen("minimum.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(ll x){pf("%lld ",x);}inline void pn(){pf("\n");}
	const int N=1e5+10;
	ll dis[N],ans;int n,m,co,head[N],col[N],minn[N];bool vis[N];
	struct node{int from,next,to,w;}e[N<<2];
	inline void add(int next,int to,int w){e[++co]=(node){next,head[next],to,w},head[next]=co;}
	std::queue<int>q;
	inline void spfa(){
		F(i,1,n)if(!col[i])dis[i]=1e18,minn[i]=1e9;else q.push(i),vis[i]=1;
		while(!q.empty()){
			int x=q.front();q.pop();vis[x]=0;
			for(register int i=head[x],j;i;i=e[i].next)if(dis[j=e[i].to]>dis[x]+e[i].w){
				dis[j]=dis[x]+e[i].w;
				if(!vis[j]){
					q.push(j);
					vis[j]=1;
				}
			}
		}
		F(i,1,co)if(dis[e[i].to]==dis[e[i].from]+e[i].w)minn[e[i].to]=min(minn[e[i].to],e[i].w);
	}
	inline short main(){
		file();
		n=read();m=read();
		F(i,1,n)col[i]=read();
		F(i,1,m){
			int x=read(),y=read(),z=read();
			add(x,y,z);add(y,x,z);
		}spfa();
		F(i,1,n)if(dis[i]==1e18){
			pf("impossible\n");
			return 0;
		}else ans+=minn[i];
		pi(ans);
		return 0;
	}
}
signed main(){return EMT::main();}

小L的数列

矩阵快速幂,大家好像都被卡常了,挂成和我暴力一个分...

Code


%: pragma GCC optimize("O3")
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("seq.in","r",stdin);freopen("seq.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int mod=998244352;
	int n,k,f[210],B[210];
	int ans=1;
	const int Md=998244353;
	inline int Ksm(int a,int b){
		// pi(a);pi(b);pn();
		int ans=1;
		while(b){
			if(b&1)ans=1ll*a*ans%Md;
			a=1ll*a*a%Md;b>>=1;
		}return ans;
	}
	struct jz{
		int a[210][210],b[210][210],c[210],d[210],e[210][210];
		inline void muls(int n){
			memset(b,0,sizeof(b));
			F(i,1,n)F(k,1,n)F(j,1,n)b[i][j]+=1ll*a[i][k]*a[k][j]%mod,b[i][j]-=b[i][j]>=mod?mod:0;
			F(i,1,n)F(j,1,n)a[i][j]=b[i][j];
		}
		inline void mul1(int n){
			memset(d,0,sizeof(d));
			F(i,1,n)F(j,1,n)d[i]+=1ll*c[j]*e[j][i]%mod,d[i]-=d[i]>=mod?mod:0;
			F(i,1,n)c[i]=d[i];
		}
		inline void mul2(int n){
			memset(b,0,sizeof(b));
			F(i,1,n)F(k,1,n)F(j,1,n)b[i][j]+=1ll*e[i][k]*a[k][j]%mod,b[i][j]-=b[i][j]>=mod?mod:0;
			F(i,1,n)F(j,1,n)e[i][j]=b[i][j];
		}
		inline void init(){
			F(i,1,k-1)a[i+1][i]=1;
			F(i,1,k)a[i][k]=B[k-i+1];
			F(i,1,k)e[i][i]=1;
		}
		inline void ksm(int n){
			while(n){
				if(n&1)mul2(k);
				muls(k);n>>=1;
			}
		}
		inline void getans(){
			F(i,1,k){
				memset(c,0,sizeof(c));
				c[i]=1;
				mul1(k);
				int tot=0;
				F(j,1,k)tot+=c[j],tot-=tot>=mod?mod:0;
				ans=1ll*ans*Ksm(f[i],c[k])%Md;
			}
		}
	}js;
	inline short main(){
		file();
		n=read(),k=read();
		F(i,1,k)B[i]=read();
		F(i,1,k)f[i]=read();
		if(n<=k){pi(f[n]);return 0;}
		js.init();
		js.ksm(n-k);
		js.getans();
		pi(ans);
		return 0;
	}
}
signed main(){return EMT::main();}

小L的疑惑

注意到从小到大求前缀和如果前缀和不能满足大于等于当前数-1那么这个区间内的数就无法填满.于是就是zz扫一遍了.

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cassert>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline ll read(){ll x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("math.in","r",stdin);freopen("math.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(ll x){pf("%lld ",x);}inline void pn(){pf("\n");}
	const int N=1e5+10;
	int n;ll a[N];
	inline short main(){
		file();
		n=read();
		F(i,1,n)a[i]=read();ll pre=0;
		std::sort(a+1,a+n+1);
		F(i,1,n){
			if(pre<a[i]-1){
				pi(pre+1);
				return 0;
			}
			pre+=a[i];
		}pi(pre+1);
		return 0;
	}
}
signed main(){return EMT::main();}

2021-10-09 18:29:00 星期六

显然也是我整的


Code



#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<set>
#include<vector>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define int ll
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline ll read(){ll x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("graph.in","r",stdin);freopen("graph.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(ll x){pf("%lld ",x);}inline void pn(){pf("\n");}
	const int N=2e5+10;
	ll n;int m;
	std::set<ll>s;std::vector<ll>hv;
	inline int gcd(int a,int b){return b?gcd(b,a%b):a;}
	inline int ask(ll n){
		ll ans=0,d=0;
		if(*s.begin()>n/2){
			ll b=*s.begin()*2-n;ans+=b;
			n-=b;
			hv.clear();
			for(auto i:s)hv.push_back(i);
			s.clear();
			for(auto i:hv)s.insert(i-b);
		}
		for(auto i:s){
			if(i<=n/2)d=gcd(d,i);
			else break;
		}
		s.erase(s.begin(),s.upper_bound(n/2));
		for(auto i:s){
			if(i+d<=n)d=gcd(d,i);
			else break;
		}
		s.erase(s.begin(),s.upper_bound(n-d));
		if(!s.size())return ans+d;
		int nn=d+(n%d);
		hv.clear();
		for(auto i:s){
			hv.push_back(nn-n+i);
		}s.clear();
		for(auto i:hv){
			s.insert(i);
		}s.insert(d);
		return ans+ask(nn);
	}
	inline short main(){
		file();
		int T=read();
		while(T--){
			n=read(),m=read();s.clear();
			F(i,1,m)s.insert(read());
			pi(ask(n));pn();
		}
		return 0;
	}
}
signed main(){return EMT::main();}

是我的你不要抢

hash竟然草过了,不说了。

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
#include<map>
#include<cassert>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	typedef unsigned long long ull;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("string.in","r",stdin);freopen("string.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int N=6e5+10;
	struct dp{int x,y;friend bool operator <(dp a,dp b){return a.x==b.x?a.y<b.y:a.x<b.x;}};
	std::vector<int>s[N];
	std::vector<ull>hs[N];
	std::map<dp,int>mp;
	ull p[N];
	int n,Q,ans[15][15];
	inline ull gethash(int i,int l,int r){return hs[i][r]-hs[i][l-1]*p[r-l+1];}
	inline bool check(int i,int j,int x){
		return gethash(i,s[i][0]-x+1,s[i][0])==gethash(j,1,x);
	}
	inline short main(){
		file();
		n=read(),Q=read();
		p[0]=1;
		F(i,1,600000)p[i]=p[i-1]*13331;
		F(i,1,n){
			char ch=getchar();
			s[i].push_back(0);
			while(!(ch>='a'&&ch<='z'))ch=getchar();
			while(ch>='a'&&ch<='z')s[i][0]++,s[i].push_back(ch),ch=getchar();
			hs[i].push_back(0);
			F(j,1,s[i][0])hs[i].push_back((ull)hs[i][j-1]*13331+s[i][j]);
		}
		if(n<=10){
			F(i,1,n)F(j,1,n)D(k,min(s[i][0],s[j][0]),1)if(check(i,j,k)){ans[i][j]=k;break;}
			while(Q--){
				int x=read(),y=read();
				pi(ans[x][y]),pn();
			}
		}else{
			while(Q--){
				int x=read(),y=read();
				int val=mp[(dp){x,y}];
				if(val>0){pi(val);pn();continue;}
				if(val==-1){pi(0);pn();continue;}
				D(i,min(s[x][0],s[y][0]),1)if(check(x,y,i)){val=i;break;}
				mp[(dp){x,y}]=(val==0?-1:val);
				pi(val);pn();
			}
		}
		return 0;
	}
}
signed main(){return EMT::main();}

最简单辣快来做

把绝对值拆开,
开四个前缀和维护即可。

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("satellite.in","r",stdin);freopen("satellite.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int N=2100;
	int n,Q,mod,a,b,h[N],x[N],y[N],s1[N],s2[N],id[N][N],pre[5][N][N];
	struct poW{
		int pa[100010],pb[100010],basa[11000],basb[11000];
		inline void init(){
			basa[0]=basb[0]=1;
			F(i,1,10000)basa[i]=1ll*basa[i-1]*a%mod;
			F(i,1,10000)basb[i]=1ll*basb[i-1]*b%mod;
			pa[1]=basa[10000];pb[1]=basb[10000];
			pa[0]=pb[0]=1;
			F(i,2,100000)pa[i]=1ll*pa[i-1]*pa[1]%mod;
			F(i,2,100000)pb[i]=1ll*pb[i-1]*pb[1]%mod;
		}
		inline int powa(int x){
			if(x<0)return 0;
			return 1ll*pa[x/10000]*basa[x%10000]%mod;
		}
		inline int powb(int x){
			if(x<0)return 0;
			return 1ll*pb[x/10000]*basb[x%10000]%mod;
		}
	}js;
	inline short main(){
		file();
		n=read(),Q=read(),read(),read(),mod=read(),a=read(),b=read();
		js.init();
		F(i,1,n)h[i]=read(),x[i]=read(),y[i]=read(),s1[i]=x[i],s2[i]=y[i];
		std::sort(s1+1,s1+n+1),std::sort(s2+1,s2+n+1);
		int len1=std::unique(s1+1,s1+n+1)-s1-1,len2=std::unique(s2+1,s2+n+1)-s2-1;
		F(i,1,n)x[i]=std::lower_bound(s1+1,s1+len1+1,x[i])-s1,
				y[i]=std::lower_bound(s2+1,s2+len2+1,y[i])-s2,
				id[x[i]][y[i]]=i;
		F(i,1,len1)F(j,1,len2){
			pre[1][i][j] =1ll*pre[1][i][j-1]*js.powb(s2[j]-s2[j-1])%mod;
			pre[1][i][j]+=1ll*pre[1][i-1][j]*js.powa(s1[i]-s1[i-1])%mod,
			pre[1][i][j]-=pre[1][i][j]>=mod?mod:0;
			pre[1][i][j]-=1ll*pre[1][i-1][j-1]*js.powb(s2[j]-s2[j-1])%mod*js.powa(s1[i]-s1[i-1])%mod,
			pre[1][i][j]+=pre[1][i][j]<0?mod:0;
			if(id[i][j])pre[1][i][j]+=h[id[i][j]]%mod,
						pre[1][i][j]-=pre[1][i][j]>=mod?mod:0;
		}
		D(i,len1,1)D(j,len2,1){
			pre[2][i][j] =1ll*pre[2][i][j+1]*js.powb(s2[j+1]-s2[j])%mod,
			pre[2][i][j]+=1ll*pre[2][i+1][j]*js.powa(s1[i+1]-s1[i])%mod,
			pre[2][i][j]-=pre[2][i][j]>=mod?mod:0,
			pre[2][i][j]-=1ll*pre[2][i+1][j+1]*js.powb(s2[j+1]-s2[j])%mod*js.powa(s1[i+1]-s1[i])%mod,
			pre[2][i][j]+=pre[2][i][j]<0?mod:0;
			if(id[i][j])pre[2][i][j]+=h[id[i][j]],pre[2][i][j]-=pre[2][i][j]>=mod?mod:0;
		}
		F(i,1,len1)D(j,len2,1){
			pre[3][i][j] =1ll*pre[3][i][j+1]*js.powb(s2[j+1]-s2[j])%mod,
			pre[3][i][j]+=1ll*pre[3][i-1][j]*js.powa(s1[i]-s1[i-1])%mod,
			pre[3][i][j]-=pre[3][i][j]>=mod?mod:0,
			pre[3][i][j]-=1ll*pre[3][i-1][j+1]*js.powb(s2[j+1]-s2[j])%mod*js.powa(s1[i]-s1[i-1])%mod,
			pre[3][i][j]+=pre[3][i][j]<0?mod:0;
			if(id[i][j])pre[3][i][j]+=h[id[i][j]]%mod,
						pre[3][i][j]-=pre[3][i][j]>=mod?mod:0;
		}
		D(i,len1,1)F(j,1,len2){
			pre[4][i][j] =1ll*pre[4][i][j-1]*js.powb(s2[j]-s2[j-1])%mod,
			pre[4][i][j]+=1ll*pre[4][i+1][j]*js.powa(s1[i+1]-s1[i])%mod,
			pre[4][i][j]-=pre[4][i][j]>=mod?mod:0,
			pre[4][i][j]-=1ll*pre[4][i+1][j-1]*js.powb(s2[j]-s2[j-1])%mod*js.powa(s1[i+1]-s1[i])%mod,
			pre[4][i][j]+=pre[4][i][j]<0?mod:0;
			if(id[i][j])pre[4][i][j]+=h[id[i][j]]%mod,
						pre[4][i][j]-=pre[4][i][j]>=mod?mod:0;
		}
		while(Q--){
			int p=read(),q=read(),ans=0;
			int l=std::lower_bound(s1+1,s1+len1+1,p)-s1;
			int r=std::lower_bound(s2+1,s2+len2+1,q)-s2;
			if(s1[l]!=p&&s2[r]!=q){
				l--,r--;
				ans+=1ll*pre[1][l][r]*js.powa(p-s1[l])%mod*js.powb(q-s2[r])%mod;
				l++;r++;
				ans+=1ll*pre[2][l][r]*js.powa(s1[l]-p)%mod*js.powb(s2[r]-q)%mod,
				ans-=ans>=mod?mod:0;
				l--;
				ans+=1ll*pre[3][l][r]*js.powa(p-s1[l])%mod*js.powb(s2[r]-q)%mod,
				ans-=ans>=mod?mod:0;
				l++;r--;
				ans+=1ll*pre[4][l][r]*js.powa(s1[l]-p)%mod*js.powb(q-s2[r])%mod,
				ans-=ans>=mod?mod:0;
				pi(ans);pn();
			}else{
				if(s1[l]==p&&s2[r]!=q){
					r--;
					ans+=1ll*pre[1][l][r]*js.powa(p-s1[l])%mod*js.powb(q-s2[r])%mod;
					l++;r++;
					ans+=1ll*pre[2][l][r]*js.powa(s1[l]-p)%mod*js.powb(s2[r]-q)%mod,
					ans-=ans>=mod?mod:0;
					l--;
					ans+=1ll*pre[3][l][r]*js.powa(p-s1[l])%mod*js.powb(s2[r]-q)%mod,
					ans-=ans>=mod?mod:0;
					l++;r--;
					ans+=1ll*pre[4][l][r]*js.powa(s1[l]-p)%mod*js.powb(q-s2[r])%mod,
					ans-=ans>=mod?mod:0;
					pi(ans);pn();
				}else if(s1[l]!=p&&s2[r]==q){
					l--;
					ans+=1ll*pre[1][l][r]*js.powa(p-s1[l])%mod*js.powb(q-s2[r])%mod;
					l++;r++;
					ans+=1ll*pre[2][l][r]*js.powa(s1[l]-p)%mod*js.powb(s2[r]-q)%mod,
					ans-=ans>=mod?mod:0;
					l--;
					ans+=1ll*pre[3][l][r]*js.powa(p-s1[l])%mod*js.powb(s2[r]-q)%mod,
					ans-=ans>=mod?mod:0;
					l++;r--;
					ans+=1ll*pre[4][l][r]*js.powa(s1[l]-p)%mod*js.powb(q-s2[r])%mod,
					ans-=ans>=mod?mod:0;
					pi(ans);pn();
				}else{
					ans+=1ll*pre[1][l][r]*js.powa(p-s1[l])%mod*js.powb(q-s2[r])%mod;
					l++;r++;
					ans+=1ll*pre[2][l][r]*js.powa(s1[l]-p)%mod*js.powb(s2[r]-q)%mod,
					ans-=ans>=mod?mod:0;
					l--;
					ans+=1ll*pre[3][l][r]*js.powa(p-s1[l])%mod*js.powb(s2[r]-q)%mod,
					ans-=ans>=mod?mod:0;
					l++;r--;
					ans+=1ll*pre[4][l][r]*js.powa(s1[l]-p)%mod*js.powb(q-s2[r])%mod,
					ans-=ans>=mod?mod:0;
					pi(ans);pn();
				}
			}
		}
		return 0;
	}
}
signed main(){return EMT::main();}


出了个大阴间题

\(f_{i,j}\)表示状态为i最大值为j的方案数,g表示a的和(注意到b和如何合并无关,所以只需要求方案数即可)。
然后就是sb状压dp了

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("repair.in","r",stdin);freopen("repair.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int mod=1e9+7;
	int s[40],a[20],n,f[1<<18][40],g[1<<18][40],k,ans1,ans2;
	std::vector<int>able[1<<18];
	inline int getans(){
		int x=a[1],y=0,ans2=0;
		F(i,2,n){
			if(x==a[i])x++;
			else x=max(x,a[i]);
			y=2*y+1,y-=y>=mod?mod:0;
			ans2+=1ll*k*x%mod,ans2-=ans2>=mod?mod:0;
			ans2+=y,ans2-=ans2>=mod?mod:0;
		}
		return x;
	}
	inline int clac(){
		int ans=0,bas=0;
		F(i,2,n){
			ans+=bas,ans-=ans>=mod?mod:0;
			bas=2*bas+1,bas-=bas>=mod?mod:0;
		}return ans;
	}
	inline short main(){
		file();
		n=read(),k=read();
		F(i,1,n)s[i]=a[i]=read(),s[i+n]=a[i]+1;
		std::sort(s+1,s+n*2+1);
		int len=std::unique(s+1,s+n*2+1)-s-1;
		std::sort(a+1,a+n+1);
		ans1=std::lower_bound(s+1,s+len+1,getans())-s;
		F(i,1,n)a[i]=std::lower_bound(s+1,s+len+1,a[i])-s;
		F(i,1,n)f[1<<(i-1)][a[i]]=1;
		F(i,1,(1<<n)-1)F(j,1,n)if(!(i&(1<<(j-1))))able[i].push_back(j);
		F(i,1,(1<<n)-1)F(j,1,len)if(f[i][j]){
			for(int x:able[i]){
				if(j==a[x]){
					int to=i|(1<<(x-1));
					f[to][j+1]+=f[i][j],f[to][j+1]-=f[to][j+1]>=mod?mod:0;
					g[to][j+1]+=1ll*f[i][j]*s[j+1]%mod,g[to][j+1]-=g[to][j+1]>=mod?mod:0;
					g[to][j+1]+=g[i][j],g[to][j+1]-=g[to][j+1]>=mod?mod:0;
				}else{
					int to=i|(1<<(x-1)),y=max(a[x],j);
					f[to][y]+=f[i][j],f[to][y]-=f[to][y]>=mod?mod:0;
					g[to][y]+=1ll*f[i][j]*s[y]%mod,g[to][y]-=g[to][y]>=mod?mod:0;
					g[to][y]+=g[i][j],g[to][y]-=g[to][y]>=mod?mod:0;
				}
			}
		}pi(s[ans1]);
		ans2+=1ll*g[(1<<n)-1][ans1]*k%mod,ans2-=ans2>=mod?mod:0;
		ans2+=1ll*f[(1<<n)-1][ans1]*clac()%mod,ans2-=ans2>=mod?mod:0;
		pi(ans2);
		return 0;
	}
}
signed main(){return EMT::main();}

2021-10-07 15:48:05 星期四

朝鲜时蔬

考场上就没看懂这题目啥意思,也不会考原题,这种结论题下次还是不会做,那也不理解了,弃了弃了。

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#define int long long
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline ll read(){ll x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("vegetable.in","r",stdin);freopen("vegetable.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	ll n;int m,k;const int mod=1e9+7;
	inline int ksm(int a,int b){
		int ans=1;
		while(b){
			if(b&1)ans=1ll*a*ans%mod;
			a=1ll*a*a%mod;
			b>>=1;
		}return ans;
	}
	int inv12=ksm(12,mod-2),inv6=ksm(6,mod-2);
	inline int he(ll x){
		return x%mod*((x+1)%mod)%mod*((2*x+1)%mod)%mod*inv6%mod;
	}
	inline int js(ll l,ll r){
		return (he(r)-he(l-1)+mod)%mod;
	}
	inline int js2(ll l,ll r){
		ll x1=(l+r),x2=r-l+1;
		if(x1%2==0)x1/=2;else x2/=2;
		return x1%mod*(x2%mod)%mod;
	}
	inline short main(){
		file();
		n=read(),m=read(),k=read();
		if(m==1&&k==1)pi(n%mod);
		if(m==2&&k==1){
			int ans=0;
			for(ll l=1,r;l<=n;l=r+1){
				r=(n/(n/l));
				ans+=(r-l+1)%mod*((n/l)%mod)%mod,ans-=ans>=mod?mod:0;
				ans-=(r-l+1)%mod;ans+=ans<0?mod:0;
			}pi(ans);
		}
		if(m==2&&k==2){
			int inv2=ksm(2,mod-2);
			pi(1ll*n%mod*((n-1)%mod)%mod*inv2%mod);
		}
		if(m==3&&k==1){
			pi((n/3)%mod);
		}
		if(m==3&&k==2){
			int ans=0;
			for(ll l=1,r;l<=n;l=r+1){
				r=(n/(n/l));
				ll a=(l-1)/2,b=(r-1)/2,aa,bb;
				if(!(l&1))aa=l+1,ans+=(n/l)%mod*(a%mod)%mod,ans-=ans>=mod?mod:0,a++;else aa=l;
				if(r&1)bb=r-1,ans+=(n/l)%mod*(b%mod)%mod,ans-=ans>=mod?mod:0,b--;else bb=r;
				if(a<=b){
					int len=((bb-aa+1)/2)%mod;
					ans+=(n/l)%mod*((a+b)%mod)%mod*len%mod;
					ans-=ans>=mod?mod:0;
				}
			}pi(ans);
		}
		if(m==3&&k==3){
			pi(n%mod*((n-1)%mod)%mod*((n-2)%mod)%mod*ksm(6,mod-2)%mod);
		}
		if(m==4&&k==1){
			if(n==4||n==5)pi(1);
			else if(n>=6){
				int ans=0;
				ans=(n/6+n/9+n/10+n/12+n/15+n/21)%mod;
				pi(ans);
			}else pi(0);
		}
		if(m==4&&k==2){
			if(n>=4&&n<=6)pi(1);
			else if(n==7)pi(3);
			else if(n==8)pi(6);
			else if(n==9)pi(9);
			else if(n==10)pi(10);
			else if(n>=11)pi(((n/11)+(n/29))%mod);
			else pi(0);
		}
		if(m==4&&k==3){
			if(n==4)pi(1);
			else if(n==5)pi(5);
			else if(n>=6){
				int ans=0;
				for(ll l=6,r;l<=n;l=r+1){
					r=(n/(n/l));
					int bas=(n/l)%mod;
					int a1=js(l,r),a2=(-6*js2(l,r)%mod+mod)%mod,a3=5*(r-l+1)%mod;
					int a4=0,a5=0;
					ll aa=l;while(aa%2==0)a4++,aa++;
					ll bb=r;while(bb%2)bb--;
					a4+=(bb-aa+1)/2;a4%=mod;
					aa=l;while(aa%3!=1){if(aa%3==0)a5++;aa++;}
					bb=r;while(bb%3)bb--;
					a5+=(bb-aa+1)/3;a5%=mod;
					int x=a1;
					x+=a2,x-=x>=mod?mod:0,x+=a3,x-=x>=mod?mod:0,x+=a4*3%mod,x-=x>=mod?mod:0,x+=a5*4%mod,x-=x>=mod?mod:0;
					x=1ll*x*inv12%mod;
					ans+=1ll*bas*x%mod,ans-=ans>=mod?mod:0;
				}pi(ans);
			}else pi(0);
		}
		if(m==4&&k==4){
			int ans=n%mod;
			ans=(n-1)%mod*ans%mod;
			ans=(n-2)%mod*ans%mod;
			ans=(n-3)%mod*ans%mod;
			pi(1ll*ans*ksm(24,mod-2)%mod);
		}
		return 0;
	}
}
signed main(){return EMT::main();}

变异大老鼠

跑出最短路后用dis数组建出图上的树,然后就是普通的sb树形dp了。考场上切了之后过大样例直接惊掉了,反正就,挺sb的。

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
#include<cassert>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("arrest.in","r",stdin);freopen("arrest.out","w",stdout);}
	inline db max(db a,db b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int N=310;
	db f[N][N],bs[N][N];std::queue<int>q;
	struct node{int next,to,w;}e[N*N*2];
	int n,m,k,dis[N],head[N],co,Hd[N],in[N];bool vis[N];
	inline void add(int next,int to,int w){e[++co]=(node){head[next],to,w},head[next]=co;}
	inline void Add(int next,int to){e[++co]=(node){Hd[next],to},Hd[next]=co;}
	inline void spfa(){
		F(i,1,n)dis[i]=1e9;
		dis[1]=0;q.push(1);
		while(!q.empty()){
			int x=q.front();q.pop();vis[x]=0;
			for(register int i=head[x],j;i;i=e[i].next)if(dis[j=e[i].to]>dis[x]+e[i].w){
				//if(j==x)continue;
				dis[j]=dis[x]+e[i].w;
				if(!vis[j]){
					vis[j]=1;
					q.push(j);
				}
			}
		}
	}
	inline void bfs(){
		q.push(1);vis[1]=1;in[1]=1;
		while(!q.empty()){
			int x=q.front();q.pop();
			for(register int i=head[x],j;i;i=e[i].next)if(!vis[j=e[i].to]){
				if(dis[j]==dis[x]+e[i].w){
					Add(x,j);Add(j,x);in[x]++,in[j]++,vis[j]=1;
					q.push(j);
				}
			}
		}
	}
	inline void dfs(int x,int fa){
		in[x]--;db bas=1.0/(db)in[x];
		for(register int i=Hd[x],j;i;i=e[i].next)if((j=e[i].to)!=fa){
			dfs(j,x);
			D(l,k,0)D(o,l,0)f[x][l]=max(f[x][l],f[x][l-o]+bas*f[j][o]);
		}
		D(i,k,0)D(j,i,0)f[x][i]=max(f[x][i],(1-bs[x][j])*f[x][i-j]+bs[x][j]);
	}
	inline short main(){
		file();
		n=read(),m=read(),k=read();
		F(i,1,m){
			int x=read(),y=read(),z=read();
			add(x,y,z),add(y,x,z);
		}spfa();bfs();
		F(i,1,n)F(j,1,k)scanf("%lf",&bs[i][j]);
		dfs(1,0);
		pf("%.6lf",f[1][k]);
		return 0;
	}
}
signed main(){return EMT::main();}

M 弟娃

用线段树维护好以每个点作为主祭坛所得的值,问的时候直接查询全局最大值即可。

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cassert>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("magic.in","r",stdin);freopen("magic.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int N=3e5+10;
	int fa[N][22],deep[N],n,m,last[N],dfn[N],ti,co,head[N];
	struct node{int next,to;}e[N<<1];
	inline void add(int next,int to){e[++co]=(node){head[next],to};head[next]=co;}
	struct seg{
		int val[N<<2],lz[N<<2];
		inline void down(int p){
			if(lz[p]){
				lz[p<<1]+=lz[p];
				val[p<<1]+=lz[p];
				lz[p<<1|1]+=lz[p];
				val[p<<1|1]+=lz[p];
				lz[p]=0;
			}
		}
		inline void change(int p,int l,int r,int ql,int qr,int v){
			if(l>=ql&&r<=qr){
				val[p]+=v;
				lz[p]+=v;
				return;
			}int mid=(l+r)>>1;down(p);
			if(qr<=mid)change(p<<1,l,mid,ql,qr,v);
			else if(ql>mid)change(p<<1|1,mid+1,r,ql,qr,v);
			else change(p<<1,l,mid,ql,mid,v),change(p<<1|1,mid+1,r,mid+1,qr,v);
			val[p]=max(val[p<<1],val[p<<1|1]);
		}
	}segm;
	inline void dfs(int k,int f){
		dfn[k]=++ti;
		for(register int i=head[k],j;i;i=e[i].next)if((j=e[i].to)!=f){
			fa[j][0]=k;deep[j]=deep[k]+1;
			F(l,1,20)fa[j][l]=fa[fa[j][l-1]][l-1];
			dfs(j,k);
		}last[k]=ti;
	}
	inline int getfa(int x,int k){
		D(i,20,0)if((1<<i)<=k)k-=(1<<i),x=fa[x][i];
		return x;
	}
	inline int getlca(int x,int y){
		if(deep[x]<deep[y])x^=y^=x^=y;
		D(i,20,0)if((1<<i)<=(deep[x]-deep[y]))x=fa[x][i];
		if(x==y)return x;
		D(i,20,0)if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
		return fa[x][0];
	}
	inline short main(){
		file();
		n=read(),m=read();
		F(i,1,n-1){
			int x=read(),y=read();
			add(x,y),add(y,x);
		}dfs(1,0);
		F(i,1,m){
			int x=read(),y=read();
			if(x==y){
				segm.change(1,1,n,1,n,1);
			}else{
				int lca=getlca(x,y);
				if(deep[x]>deep[y])x^=y^=x^=y;
				if(lca==x){
					int dis=deep[y]-deep[x];
					segm.change(1,1,n,dfn[y],last[y],1);
					y=getfa(y,dis-1);
					if(dfn[y]>1)segm.change(1,1,n,1,dfn[y]-1,1);
					if(last[y]<n)segm.change(1,1,n,last[y]+1,n,1);
				}else{
					segm.change(1,1,n,dfn[x],last[x],1);
					segm.change(1,1,n,dfn[y],last[y],1);
				}
			}pi(segm.val[1]);pn();
		}
		return 0;
	}
}
signed main(){return EMT::main();}

签到题

真·签到题。
(在此膜拜yspm巨佬考试结束前两分钟迅速想出正解并切掉此题)
看每个点的度数如果不是c的倍数就ans++,没了。

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("qiandao.in","r",stdin);freopen("qiandao.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int N=1e6+10;
	int n,m,k,c,in[2][N],ans;
	inline short main(){
		file();
		n=read(),m=read(),k=read(),c=read();
		F(i,1,k){
			int x=read(),y=read();
			in[1][x]++,in[0][y]++;
		}
		F(i,1,n)ans+=(in[1][i]%c==0?0:1);
		F(i,1,m)ans+=(in[0][i]%c==0?0:1);
		pi(ans);
		return 0;
	}
}
signed main(){return EMT::main();}

2021-10-06 21:32:32 星期三

挖掘机

用倍增数组维护i点跳\(2^j\)次能跳到哪里,对于每个深度单独计算即可。

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<set>
#include<algorithm>
#include<cassert>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("blueshit.in","r",stdin);freopen("blueshit.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int N=1e5+10;
	int h,w,k,q,a[15][N],nxt[15][N],f[15][N][18],n;
	inline short main(){
		file();
		h=read(),n=w=read(),k=read(),q=read();
		F(i,1,h)F(j,1,w){
			char ch=getchar();
			while(ch!='X'&&ch!='.')ch=getchar();
			a[i][j]=ch=='X'?1:0;
		}
		int last;
		F(i,1,h){
			last=w+1;
			D(j,w,1){
				nxt[i][j]=last;
				if(a[i][j])last=j;
			}
		}
		F(i,1,h){
			F(j,1,w){
				if(!a[i][j])j=nxt[i][j];
				if(j>w)break;
				int x=j+k;
				if(x<=n){
					if(a[i][x])f[i][j][0]=x;
					else f[i][j][0]=nxt[i][x];
				}else{
					f[i][j][0]=n+1;
				}
			}
			F(k,1,17){
				F(j,1,w){
					if(!a[i][j])j=nxt[i][j];
					if(j>w)break;
					int x=f[i][j][k-1];if(!x){pi(i),pi(j),pi(k-1);return 0;}
					if(x<=n)f[i][j][k]=f[i][x][k-1];
					else f[i][j][k]=n+1;
				}
			}
		}
		while(q--){
			int d=read(),l=read(),r=read(),ans=0;
			F(i,1,d){
				int now=l;
				if(!a[i][now])now=nxt[i][now];
				if(now>r)continue;
				D(j,17,0)if(f[i][now][j]<=r){
					ans+=(1<<j),now=f[i][now][j];
				}ans++;
			}pi(ans);pn();
		}
		return 0;
	}
}
signed main(){return EMT::main();}

文件名blueshit可太草了

暴雨

\(f_{i,j,p,0/1}\)表示前i位,当前最大值为j,删了p个数,目前加和是奇数/偶数的方案数,由于j是1e9的所以我们只需要对每个i存下来前k+1大的值,用map映射一下j对于i是第几大值,用一个set即可简单实现,然后转移方程式很naive,最后枚举大于等于第k+1大的值的值的位置,用它左右两边小于它的值的f和g数组统计一下即可。

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<map>
#include<set>
#include<vector>
#include<cassert>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("rain.in","r",stdin);freopen("rain.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int N=25100,mod=1e9+7;
	int f[N][30][30][2],g[N][30][30][2],hv[N][30],n,k,a[N],hv2[N][30],p[N],ans;
	std::map<int,int>mp[N],mp2[N];
	std::multiset<int>s,s2;
	inline bool com(int i,int j){return a[i]>a[j];}
	inline short main(){
		file();
		n=read(),k=read();
		F(i,1,n)a[i]=read();
		F(i,1,n)p[i]=i;
		s.insert(0);
		F(i,1,n){
			s.insert(a[i]);
			auto it=s.end();
			F(j,1,k+1){
				if(it==s.begin())break;
				it--;
				hv[i][++hv[i][0]]=*it;
				mp[i][*it]=hv[i][0];
			}
		}std::sort(p+1,p+n+1,com);
		f[0][1][0][0]=1;
		hv[0][hv[0][0]=1]=0;
		F(i,0,n-2)F(j,1,hv[i][0])F(p,0,min(k,i))F(t,0,1)if(f[i][j][p][t]){
			// pf("i:%d j:%d p:%d t:%d val:%d a[i]:%d->\n",i,j,p,t,f[i][j][p][t],a[i]);
			if(a[i+1]>=hv[i][j]){
				// pf("1\n");
				int x=mp[i+1][a[i+1]];bool y=t^(hv[i][j]&1);
				if(x)f[i+1][x][p][t]+=f[i][j][p][t],f[i+1][x][p][t]-=f[i+1][x][p][t]>=mod?mod:0;
				// pf("i+1:%d x:%d p:%d y:%d val:%d\n",i+1,x,p,y,f[i+1][x][p][t]);
				x=mp[i+1][hv[i][j]];
				// pf("i+1:%d hv[i][j]:%d mp[i+1][hv[i][j]: %d\n",i+1,hv[i][j],x);
				if(x)f[i+1][x][p+1][y]+=f[i][j][p][t],f[i+1][x][p+1][y]-=f[i+1][x][p+1][y]>=mod?mod:0;
				// pf("i+1:%d x:%d p+1:%d y:%d val:%d\n",i+1,x,p+1,y,f[i+1][x][p+1][y]);
			}else{
				// pf("2\n");
				int x=mp[i+1][hv[i][j]];bool y=t^((hv[i][j]-a[i+1])&1);
				if(x)f[i+1][x][p][y]+=f[i][j][p][t],f[i+1][x][p][y]-=f[i+1][x][p][y]>=mod?mod:0;
				// pf("i+1:%d x:%d p:%d y:%d val:%d\n",i+1,x,p,y,f[i+1][x][p][y]);
				y=t^(hv[i][j]&1);
				if(x)f[i+1][x][p+1][y]+=f[i][j][p][t],f[i+1][x][p+1][y]-=f[i+1][x][p+1][y]>=mod?mod:0;
				// pf("i+1:%d x:%d p+1:%d y:%d val:%d\n",i+1,x,p+1,y,f[i+1][x][p+1][y]);
			}//pn();
		}
		g[n+1][1][0][0]=1;
		hv2[n+1][hv2[n+1][0]=1]=0;
		s2.insert(0);
		D(i,n,1){
			s2.insert(a[i]);
			auto it=s2.end();
			F(j,1,k+1){
				if(it==s2.begin())break;
				it--;
				hv2[i][++hv2[i][0]]=*it;
				mp2[i][*it]=hv2[i][0];
			}
		}
		D(i,n+1,3)F(j,1,hv2[i][0])F(p,0,min(k,n-i+1))F(t,0,1)if(g[i][j][p][t]){
			if(a[i-1]>=hv2[i][j]){
				int x=mp2[i-1][a[i-1]];bool y=t^(hv2[i][j]&1);
				if(x)g[i-1][x][p][t]+=g[i][j][p][t],g[i-1][x][p][t]-=g[i-1][x][p][t]>=mod?mod:0;
				x=mp2[i-1][hv2[i][j]];
				if(x)g[i-1][x][p+1][y]+=g[i][j][p][t],g[i-1][x][p+1][y]-=g[i-1][x][p+1][y]>=mod?mod:0;
			}else{
				int x=mp2[i-1][hv2[i][j]];bool y=t^((hv2[i][j]-a[i-1])&1);
				if(x)g[i-1][x][p][y]+=g[i][j][p][t],g[i-1][x][p][y]-=g[i-1][x][p][y]>=mod?mod:0;
				y=t^(hv2[i][j]&1);
				if(x)g[i-1][x][p+1][y]+=g[i][j][p][t],g[i-1][x][p+1][y]-=g[i-1][x][p+1][y]>=mod?mod:0;
			}
		}
		F(i,1,n){
			if(a[p[i]]<a[p[k+1]])break;
			int x=p[i],v=a[x];
			D(j,hv[x-1][0],1){
				if(hv[x-1][j]>=v)break;
				D(l,hv2[x+1][0],1){
					if(hv2[x+1][l]>v)break;
					F(p,0,k)
						ans+=1ll*f[x-1][j][p][0]*g[x+1][l][k-p][0]%mod,ans-=ans>=mod?mod:0,
						ans+=1ll*f[x-1][j][p][1]*g[x+1][l][k-p][1]%mod,ans-=ans>=mod?mod:0;
				}
			}
		}pi(ans);
		return 0;
	}
}
signed main(){return EMT::main();}

2021-10-06 07:18:31 星期三

黑客2

高精度+记忆化搜索,被卡常可太ex了啊。

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
%:pragma GCC optimize("O3")
namespace emt{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	int n,m,k;
	const int N=20000;
	struct node{
		int num[N],wei;
		inline void clear(){
			F(i,1,wei)num[i]=0;
		}
		inline void print(){
			D(i,wei,1)pf("%d",num[i]);
			if(!wei)pi(0);
			pn();
		}
	}c,base,a,ans;
	node operator +(node a,node b){
		c.clear();
		c.wei=max(a.wei,b.wei)+10;
		F(i,1,max(a.wei,b.wei)+5){
			c.num[i]+=a.num[i]+b.num[i];
			c.num[i+1]+=c.num[i]/10;
			c.num[i]%=10;
		}
		while(!c.num[c.wei]&&c.wei>0)c.wei--;
		return c;
	}
	node operator *(node a,int b){
		c.clear();
		c.wei=a.wei+20;
		F(i,1,a.wei+5){
			c.num[i]+=a.num[i]*b;
			c.num[i+1]+=c.num[i]/10;
			c.num[i]%=10;
		}
		while(!c.num[c.wei]&&c.wei>0)c.wei--;
		return c;
	}
	inline int gc(){char ch=getchar();while(ch<'0'||ch>'9')ch=getchar();return ch-'0';}
	inline short main(){
		base.wei=1;base.num[1]=1;
		F(i,1,n-1)base=base*k;
		a=base*k;
		a.print();
		F(i,1,n){
			F(j,1,k)
				ans=ans+base*j;
			base=base*10;
		}
		ans.print();
		return 0;
	}
}
namespace EMT{
	typedef long long ll;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0;char ch=getchar();while(ch<'0'||ch>'9')ch=getchar();while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x;}
	inline void file(){freopen("hacker2.in","r",stdin);freopen("hacker2.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int N=501,mod=1e9;
	int n,m,k,zT[15],ji[N][1<<9],able[1<<9][11],tot;
	struct node{
		ll num[115];int wei;
		inline void clear(){
			F(i,1,wei)num[i]=0;
		}
		inline void print(){
			pf("%lld",num[wei]);
			D(i,wei-1,1)pf("%09lld",num[i]);
		}
		inline void operator +=(node &b){
			wei=max(wei,b.wei)+1;
			F(i,1,wei-1){
				num[i]+=b.num[i];
				num[i+1]+=num[i]/mod;
				num[i]%=mod;
			}
			while(!num[wei]&&wei>0)wei--;
		}
		inline void add(node &b,node c){
			wei=max(max(b.wei,c.wei),wei)+1;
			F(i,1,wei){
				num[i]+=b.num[i]+c.num[i];
				num[i+1]+=num[i]/mod;
				num[i]%=mod;
			}
			while(!num[wei]&&wei>0)wei--;
		}
		inline void addd(node &b,node &c,node &d){
			wei=max(max(b.wei,c.wei),max(wei,d.wei))+2;
			int x=wei;
			F(i,1,wei){
				num[i]+=b.num[i]+c.num[i]+d.num[i];
				num[i+1]+=num[i]/mod;
				num[i]%=mod;
			}
			while(!num[wei]&&wei>0)wei--;
		}
	}f[513025],c,d,e;
	inline node operator *(node &a,int b){
		c.clear();
		c.wei=a.wei+1;
		F(i,1,a.wei){
			c.num[i]+=a.num[i]*b;
			c.num[i+1]+=c.num[i]/mod;
			c.num[i]%=mod;
		}
		while(!c.num[c.wei]&&c.wei>0)c.wei--;
		return c;
	}
	inline node p10(node a,int x){
		d.clear();
		register int jin=x/9;d.wei=a.wei+jin;
		F(i,1,a.wei)d.num[i+jin]=a.num[i];
		register int base=1,sheng=x%9;
		if(!sheng)return d;
		while(sheng--)base=base*10;
		return d*base;
	}
	int dfs(int x,int zt){
		if(ji[x][zt])return ji[x][zt];
		if(!(x-n)){
			ji[x][zt]=++tot;
			f[tot].wei=1,f[tot].num[1]=1;
			return tot++;
		}
		ji[x][zt]=++tot;register int now=tot++,last,lastt,cnt=0;
		F(i,1,able[zt][0]){
			register int j=able[zt][i];
			register int y=dfs(x+1,zt|(1<<(j-1)));
			++cnt;
			if(!(cnt-3)){
				f[now].addd(f[y],f[last],f[lastt]);
				cnt=0;
			}lastt=last,last=y;
			f[now+1].add(f[y+1],p10(f[y]*j,n-x-1));
		}
		if(cnt==1)f[now]+=f[last];
		if(cnt==2)f[now].add(f[last],f[lastt]);
		return now;
	}
	inline short main(){
		file();
		n=read(),m=read(),k=read();
		if(!m){
			emt::n=n;emt::m=m;emt::k=k;
			return emt::main();
		}
		F(i,1,m){
			int x=read(),y=read();
			zT[y]|=(1<<(x-1));
		}
		F(i,0,(1<<k)-1)F(j,1,k)if(!(i&zT[j]))able[i][++able[i][0]]=j;
		int x=dfs(0,0);
		f[x].print(),pn(),f[x+1].print();
		fclose(stdin),fclose(stdout);
		return 0;
	}
}
signed main(){return EMT::main();}

黑客

考场上一开始看到最优策略就脑袋大直接跳了,剩下一个小时的时候才发现这是个sb题,然后就切了。
主要方法就是找到两个范围的交集即可。

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define int long long
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("hacker.in","r",stdin);freopen("hacker.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%lld ",x);}inline void pn(){pf("\n");}
	int A,B,C,D,ans;
	const int mod=1e9+7;
	int a[5];
	inline int gcd(int a,int b){return b?gcd(b,a%b):a;}
	inline short main(){
		file();
		A=read(),B=read(),C=read(),D=read();
		F(i,2,999){
			F(j,1,i-1){
				int k=i-j;
				int l,r,L,R;
				if(A%j==0)l=A/j;else l=A/j+1;
				r=B/j;
				if(C%k==0)L=C/k;else L=C/k+1;
				R=D/k;
				//if(j==5&&k==4)pi(l),pi(r),pi(L),pi(R),pn();
				if(r<l||R<L)continue;
				if(r<L||l>R)continue;
				if(gcd(j,k)>1)continue;
				if((l>=L&&r<=R)||(L>=l&&R<=r))ans+=min(R-L+1,r-l+1)*i%mod,ans-=ans>=mod?mod:0;
				else{
					a[1]=l,a[2]=r,a[3]=L,a[4]=R;
					std::sort(a+1,a+5);
					ans+=(a[3]-a[2]+1)*i%mod,ans-=ans>=mod?mod:0;
				}
			}
		}pi(ans);
		return 0;
	}
}
signed main(){return EMT::main();}

2021-10-05 06:04:53 星期二

切题

将为题转化为\(\sum\limits_{i=1}^{k}c_i-a_i\)是否对任意k都\(>=0\),用线段树维护即可。

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cassert>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("problem.in","r",stdin);freopen("problem.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int N=2.5e5+10;
	int sum[N],a[N],s[N],n,m,b[N],c[N];
	struct seg{
		int val[N<<2],lz[N<<2];
		inline void down(int p){
			if(lz[p]){
				val[p<<1]+=lz[p];
				val[p<<1|1]+=lz[p];
				lz[p<<1]+=lz[p];
				lz[p<<1|1]+=lz[p];
				lz[p]=0;
			}
		}
		inline void change(int p,int l,int r,int ql,int qr,int v){
			if(l>=ql&&r<=qr){
				val[p]+=v;
				lz[p]+=v;
				return;
			}int mid=(l+r)>>1;down(p);
			if(qr<=mid)change(p<<1,l,mid,ql,qr,v);
			else if(ql>mid)change(p<<1|1,mid+1,r,ql,qr,v);
			else change(p<<1,l,mid,ql,mid,v),change(p<<1|1,mid+1,r,mid+1,qr,v);
			val[p]=min(val[p<<1],val[p<<1|1]);
		}
		inline void build(int p,int l,int r){
			if(l==r){val[p]=sum[l];return;}
			int mid=(l+r)>>1;
			build(p<<1,l,mid),build(p<<1|1,mid+1,r);
			val[p]=min(val[p<<1|1],val[p<<1]);
		}
	}segm;
	inline bool com(int i,int j){return i>j;}
	inline short main(){
		file();
		n=read(),m=read();
		F(i,1,n)s[i]=a[i]=read();
		F(i,1,m)b[i]=read(),c[min(b[i],n)]++;
		D(i,n,1)c[i]+=c[i+1];
		std::sort(s+1,s+n+1,com);
		F(i,1,n)sum[i]=sum[i-1]+c[i]-s[i];
		segm.build(1,1,n);
		int Q=read();
		s[0]=1e9,s[n+1]=-1e9;
		while(Q--){
			int opt=read(),x=read();
			if(opt==1){
				int l=1,r=n,ans=0;
				while(l<=r){
					int mid=(l+r)>>1;
					if(s[mid]<=a[x])r=mid-1,ans=mid;
					else l=mid+1;
				}
				a[x]++;s[ans]++;
				if(s[ans-1]>=s[ans])segm.change(1,1,n,ans,n,-1);
				else{
					std::swap(s[ans-1],s[ans]);
					segm.change(1,1,n,ans-1,n,-1);
				}
			}else if(opt==2){
				int l=1,r=n,ans=0;
				while(l<=r){
					int mid=(l+r)>>1;
					if(s[mid]>=a[x])l=mid+1,ans=mid;
					else r=mid-1;
				}
				a[x]--;s[ans]--;
				if(s[ans+1]<=s[ans])segm.change(1,1,n,ans,n,1);
				else{
					std::swap(s[ans],s[ans+1]);
					segm.change(1,1,n,ans+1,n,1);
				}
			}else if(opt==3){
				if(b[x]>=n||b[x]<0)b[x]++;
				else{
					b[x]++;
					segm.change(1,1,n,b[x],n,1);
				}
			}else{
				if(b[x]>n||b[x]<=0)b[x]--;
				else{
					b[x]--;
					segm.change(1,1,n,b[x]+1,n,-1);
				}
			}
			if(segm.val[1]>=0)pi(1);else pi(0);pn();
		}
		return 0;
	}
}
signed main(){return EMT::main();}

玩水

发现只需要三条路径,那么称\(c_{i+1,j}=c_{i,j+1}\)\(i,j\)为好位置,只需要有相邻的两个好位置或者左上右下关系即可,使用二维前缀和。

Code



#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<unordered_map>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	typedef unsigned long long ull;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("water.in","r",stdin);freopen("water.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int N=1100;
	char a[N][N];int n,m,pre[N][N];bool fl=0;
	inline char gc(){
		char ch=getchar();
		while(ch<'a'||ch>'z')ch=getchar();
		return ch;
	}
	inline void solve(){
		n=read(),m=read();
		F(i,1,n)F(j,1,m)a[i][j]=gc();
		memset(pre,0,sizeof(pre));
		F(i,1,n-1)F(j,1,m-1){
			pre[i][j]|=pre[i-1][j];pre[i][j]|=pre[i][j-1];
			if(a[i][j+1]==a[i+1][j]){
				if(pre[i][j]||pre[i][j+1]||pre[i+1][j]){pi(1);pn();return;}
				pre[i+1][j+1]=1;
			}
		}pi(0);pn();return;
	}
	inline short main(){
		file();
		int T=read();
		while(T--)solve();
		return 0;
	}
}
signed main(){return EMT::main();}

2021-10-04 06:13:22 星期一

下落的小球

分在子树外和子树内两部分对子树进行合并,合并时是\(C_{x+y}^{x}\)的方案树最后两部分乘起来加上子树贡献即可。

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("ball.in","r",stdin);freopen("ball.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int mod=1e9+7,N=1e6+10;
	struct node{int next,to;}e[N];
	int head[N],co,n,siz[N],b[N],a[N],f[N],jc[N],inv[N],r[N];
	inline void add(int next,int to){e[++co]=(node){head[next],to};head[next]=co;}
	inline int C(int n,int m){return 1ll*jc[n]*inv[m]%mod*inv[n-m]%mod;}
	inline void dfs(int k){
		siz[k]=1;b[k]=a[k];int A=1,B=1,base=1,aa=0,bb=0;
		for(register int i=head[k],j=e[i].to;i;i=e[i].next,j=e[i].to){
			dfs(j);base=1ll*base*f[j]%mod;
			A=1ll*A*C(aa+r[j],r[j])%mod;
			B=1ll*B*C(bb+siz[j],siz[j])%mod;
			aa+=r[j],bb+=siz[j];
			b[k]+=b[j];siz[k]+=siz[j];
		}r[k]=b[k]-siz[k];
		f[k]=1ll*A*B%mod*base%mod;
	}
	inline short main(){
		file();
		n=read();
		F(i,2,n)add(read(),i);
		F(i,1,n)a[i]=read();
		jc[0]=inv[0]=inv[1]=1;
		F(i,1,n)jc[i]=1ll*jc[i-1]*i%mod;
		F(i,2,n)inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
		F(i,2,n)inv[i]=1ll*inv[i-1]*inv[i]%mod;
		dfs(1);pi(f[1]);
		return 0;
	}
}
signed main(){return EMT::main();}

数据恢复

用set维护哪个最优,如果当前最优可以点亮则直接点亮,否则将它和父亲结点结合重新插入set,一直到所有元素都被取出set即可。

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<set>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("data.in","r",stdin);freopen("data.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(ll x){pf("%lld ",x);}inline void pn(){pf("\n");}
	const int N=3e5+10;
	ll ans;int sum;
	struct dp{
		int a,b,fa,id;
		friend bool operator <(dp i,dp j){return 1ll*j.a*i.b==1ll*i.a*j.b?(i.fa==j.fa?i.id<j.id:i.fa<j.fa):1ll*j.a*i.b>1ll*i.a*j.b;}
	}p[N];
	std::multiset<dp>s;
	int n,fa[N];bool vis[N];
	inline int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
	inline short main(){
		file();
		n=read();
		F(i,1,n)fa[i]=i;
		F(i,2,n)p[i].fa=read();
		F(i,1,n)p[i].a=read(),p[i].b=read(),sum+=p[i].a,p[i].id=i;
		sum-=p[1].a;
		ans+=1ll*p[1].b*sum;
		vis[1]=1;
		F(i,2,n)s.insert(p[i]);
		while(s.size()){
			auto it=s.begin();
			dp x=*it;s.erase(it);
			int fy=find(x.fa);
			if(vis[fy]){
				sum-=x.a;
				ans+=1ll*x.b*sum;
				vis[x.id]=1;
			}else{
				auto It=s.lower_bound(p[fy]);
				s.erase(It);
				fa[x.id]=fy;
				ans+=1ll*p[fy].b*x.a;
				p[fy].a+=x.a,p[fy].b+=x.b;
				s.insert(p[fy]);
			}
		}pi(ans);
		return 0;
	}
}
signed main(){return EMT::main();}

2021-10-03 06:04:52 星期日

虚构推理

大模拟。二分偏离角度即可。细节较多。

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<assert.h>
#include<vector>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("unreal.in","r",stdin);freopen("unreal.out","w",stdout);}
	inline db max(db a,db b){return a>b?a:b;}inline db min(db a,db b){return a<b?a:b;}
	inline void pi(db x){pf("%.6lf ",x);}inline void pn(){pf("\n");}
	const int N=51000;
	int n,co,cf[N<<1];db s[N<<1];
	inline db abs(db x){return x<0?-x:x;}
	struct tim{db h,m;}a[N];
	struct dp{db l,r;int L,R,thr;}b[N];
	inline tim get(int x,int y,int z){
		if(x>=12)x-=12;
		tim ans;ans.h=x*30;ans.m=y*6;
		ans.h+=(db)y*0.5;ans.m+=(db)z*0.1;
		ans.h+=(db)z/120.0;
		return ans;
	}
	struct node{db l,r;int thr;};
	inline bool check(db range){
		std::vector<node>v1,v2;
		// pi(range);pn();
		memset(cf,0,sizeof(cf));co=0;
		F(i,1,n){
			b[i]=(dp){a[i].h-range,a[i].h+range,0};
			if(b[i].l<0){
				b[i].thr=1;
				b[i].l+=360;s[++co]=b[i].l;
			}else s[++co]=b[i].l;
			if(b[i].r>360){
				b[i].thr=1;
				b[i].r-=360;s[++co]=b[i].r;
			}else s[++co]=b[i].r;
		}
		s[++co]=0;s[++co]=360;
		std::sort(s+1,s+co+1);
		int len=std::unique(s+1,s+co+1)-s-1;
		F(i,1,n){
			b[i].L=std::lower_bound(s+1,s+len+1,b[i].l)-s;
			b[i].R=std::lower_bound(s+1,s+len+1,b[i].r)-s;
		}
		F(i,1,n)if(b[i].thr)++cf[b[i].L],++cf[1],--cf[b[i].R+1];else ++cf[b[i].L],--cf[b[i].R+1];
		db l,r;bool fl=0;
		F(i,1,len)cf[i]+=cf[i-1];
		if(cf[1]==n){
			fl=1;
			int key=1;
			while(cf[key+1]==n)key++;
			r=s[key];
			key=len+1;
			while(cf[key-1]==n)key--;
			if(key!=len+1)l=s[key],v1.push_back((node){l,r,1});
			else l=0,v1.push_back((node){l,r,0});
		}
		F(i,1,len)if(cf[i]==n){
			fl=1;
			l=s[i];int key=i;
			while(cf[key+1]==n)key++;
			r=s[key];
			v1.push_back((node){l,r,0});
			i=key;
		}
		if(!fl)return 0;
		memset(cf,0,sizeof(cf));co=0;
		F(i,1,n){
			b[i]=(dp){a[i].m-range,a[i].m+range,0};
			if(b[i].l<0){
				b[i].thr=1;
				b[i].l+=360;s[++co]=b[i].l;
			}else s[++co]=b[i].l;
			if(b[i].r>360){
				b[i].thr=1;
				b[i].r-=360;s[++co]=b[i].r;
			}else s[++co]=b[i].r;
		}
		s[++co]=0;s[++co]=360;
		std::sort(s+1,s+co+1);
		len=std::unique(s+1,s+co+1)-s-1;
		F(i,1,n){
			b[i].L=std::lower_bound(s+1,s+len+1,b[i].l)-s;
			b[i].R=std::lower_bound(s+1,s+len+1,b[i].r)-s;
		}
		F(i,1,n)if(b[i].thr)++cf[b[i].L],++cf[1],--cf[b[i].R+1];else ++cf[b[i].L],--cf[b[i].R+1];
		db ll,rr;fl=0;
		F(i,1,len)cf[i]+=cf[i-1];
		if(cf[1]==n){
			fl=1;
			int key=1;
			while(cf[key+1]==n)key++;
			rr=s[key];
			key=len+1;
			while(cf[key-1]==n)key--;
			if(key!=len+1)ll=s[key],v2.push_back((node){ll,rr,1});
			else ll=0,v2.push_back((node){ll,rr,0});
		}
		F(i,1,len)if(cf[i]==n){
			fl=1;
			ll=s[i];int key=i;
			while(cf[key+1]==n)key++;
			rr=s[key];i=key;
			v2.push_back((node){ll,rr,0});
		}if(!fl)return 0;
		int thr,thrr;
		for(auto t:v1){
			for(auto tt:v2){
				l=t.l,r=t.r,thr=t.thr;
				if(thr){
					l-=360;
					while(l<0)l+=30,r+=30;
				}
				r-=(int)(l/30)*30,l-=(int)(l/30)*30;
				ll=tt.l,rr=tt.r,thrr=tt.thr;
				if(r-l>=30)return 1;
				if(thrr)rr+=360;
				ll/=12.0,rr/=12.0;
				if(rr<l||ll>r){
					ll+=30,rr+=30;
					if(rr<l||ll>r){
						l+=30,r+=30;
						ll-=30,rr-=30;
						if(rr<l||ll>r){
							ll+=30,rr+=30;
							if(rr<l||ll>r)continue;
							return 1;
						}else return 1;
					}else return 1;
				}else return 1;
			}
		}return 0;
	}
	inline short main(){
		file();	
		n=read();
		F(i,1,n){
			int x=read(),y=read(),z=read();
			a[i]=get(x,y,z);
		}
		// F(i,1,n)pi(a[i].h),pi(a[i].m),pn();
		db l=0,r=180,ans=180;
		while(r-l>=1e-7){
			db mid=(l+r)/2.0;
			if(check(mid))r=ans=mid;
			else l=mid;
		}pi(ans);
		return 0;
	}
}
signed main(){return EMT::main();}

树上竞技

考虑每条边的贡献,设这条边左边有s个点则贡献是:

\[\sum\limits_{i=1}^{m-1}C_{s}^{i}\times C_{n-s}^{m-i} \times min(i,m-i) \]

将式子拆成:

\[\sum\limits_{i-1}^{k}if_i+(n-i)f_{n-i}+[m \mod 2==0]C_{s-1}^{i-1}\times C_{n-s}^{\frac{m}{2}}\times \frac{m}{2} \]

递推即可。

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("meeting.in","r",stdin);freopen("meeting.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int mod=1e9+7,N=1e6+10;
	inline int ksm(int a,int b){int ans=1;while(b){if(b&1)ans=1ll*a*ans%mod;a=1ll*a*a%mod;b>>=1;}return ans;}
	struct node{int next,to;}e[N<<1];
	int co,head[N],n,m,siz[N],inv[N],jc[N],g[N],f[N],ans;
	inline void add(int next,int to){e[++co]=(node){head[next],to};head[next]=co;}
	inline void Dfs(int k,int fa){
		for(register int i=head[k],j;i;i=e[i].next)if((j=e[i].to)!=fa)
			Dfs(j,k),ans+=f[siz[j]],ans-=ans>=mod?mod:0;
	}
	inline void dfs(int k,int fa){
		siz[k]=1;
		for(register int i=head[k],j;i;i=e[i].next)if((j=e[i].to)!=fa)dfs(j,k),siz[k]+=siz[j];
	}
	inline int C(int n,int m){
		if(n<m||m<0)return 0;
		return 1ll*jc[n]*inv[m]%mod*inv[n-m]%mod;
	}
	inline short main(){
		file();
		n=read(),m=read();
		F(i,2,n){
			int x=read();
			add(i,x),add(x,i);
		}dfs(1,0);
		jc[0]=inv[1]=inv[0]=1;
		F(i,1,n)jc[i]=1ll*jc[i-1]*i%mod;
		inv[n]=ksm(jc[n],mod-2);
		D(i,n-1,2)inv[i]=1ll*inv[i+1]*(i+1)%mod;
		g[1]=C(n-1,m-1);
		int k=(m-1)/2;
		if(m==2)F(i,1,n)f[i]=1ll*C(i,m/2)*C(n-i,m/2)%mod*(m/2)%mod;
		else{
			F(i,1,n-1)g[i+1]=(1ll*g[i]-1ll*C(i-1,k-1)*C(n-i-1,m-k-1)%mod+mod)%mod;
			F(i,1,n)f[i]=(1ll*i*g[i]%mod+1ll*(n-i)*g[n-i]%mod)%mod+(m%2==0?1ll*C(i,m/2)*C(n-i,m/2)%mod*(m/2)%mod:0),f[i]-=f[i]>=mod?mod:0;
		}
		Dfs(1,0);
		pi(ans);
		return 0;
	}
}
signed main(){return EMT::main();}

接力比赛

用randomshuffle打乱数据并将第二组看成负权忽视偏离0较远的量。

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("game.in","r",stdin);freopen("game.out","w",stdout);}
	inline ll max(ll a,ll b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(ll x){pf("%lld ",x);}inline void pn(){pf("\n");}
	const int N=1e3+10;
	int n,m,cnt;ll f[N*200],g[N*200];
	struct pt{int a,b;}a[N<<1];
	inline short main(){
		file();
		n=read(),m=read();
		F(i,1,n)++cnt,a[cnt].a=read(),a[cnt].b=read();
		F(i,1,m)++cnt,a[cnt].a=-read(),a[cnt].b=read();
		std::random_shuffle(a+1,a+cnt+1);
		memset(f,-1,sizeof(f));
		F(i,1,cnt){
			F(j,0,100000)g[j]=f[j];
			F(j,-50000,50000)if(f[j+50000]!=-1&&j+a[i].a+50000<=100000&&j+a[i].a+50000>=0)
			g[a[i].a+j+50000]=max(g[a[i].a+j+50000],f[j+50000]+a[i].b);
			F(j,0,100000)f[j]=g[j];
			f[a[i].a+50000]=max(f[a[i].a+50000],a[i].b);
		}pi(f[50000]);
		return 0;
	}
}
signed main(){return EMT::main();}

2021-09-29 20:59:53 星期三

置换

\(f_{i,j}\)表示长度为i的置换lcm为j的方案数,于是可以dfs搜出\(<\sqrt{n}\)的质数lcm,
转移方程是:

\[f_{i+as,lcm(y,s)}=f_{i,y}\times C_{i+as}^{as} \times ((s-1)!)^a \times \frac{1}{a!} \]

可重排列最后形式为\(\frac{n!}{\prod x!}\)由于最后乘上\((x-1)!\)除以\(n!\)所以直接乘\(\frac{1}{\prod x!}\)\(a!\)逆元即可。

Code


#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
    #define int long long
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("perm.in","r",stdin);freopen("perm.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
    const int N=210,M=2100;
    int n,mod,f[N][M],co,prime[20]={0,2,3,5,7,11,13,17,19},rk[N],p[N],g[N][M],inv[N];ll nd[M];
    inline void dfs(int x,int sum,ll mul){
        if(x>6){nd[++co]=mul;return;}
        if(sum>n)return;
        dfs(x+1,sum,mul);
        ll base=1;
        F(i,1,n){
            base=base*prime[x];
            if(sum+base>n)break;
            dfs(x+1,sum+base,mul*base);
        }
    }
    inline int gcd(int a,int b){return b?gcd(b,a%b):a;}
    inline ll lcm(int a,int b){
        return 1ll*a/gcd(a,b)*b;
    }
    inline int get(int a,int b){
        return std::lower_bound(nd+1,nd+co+1,lcm(a,b))-nd;
    }
	inline short main(){
        file(); 
        n=read(),mod=read();
        dfs(1,0,1);f[0][1]=1;std::sort(nd+1,nd+co+1);
        inv[0]=inv[1]=1;
        F(i,2,n)inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
        F(i,1,n){
            rk[i]=p[i]=i;
            F(j,1,6)while(!(p[i]%prime[j]))p[i]/=prime[j];
        }std::sort(rk+1,rk+n+1,[](int i,int j){return p[i]<p[j];});
        for(int i=1,j=1;i<=n;i=j){
            F(k,0,n)F(l,0,co)g[k][l]=f[k][l];
            while(p[rk[i]]==p[rk[j]]){
                int now=rk[j];j++;
                D(k,co,1){
                    int nxt=get(nd[k],now/p[now]);
                    if(nxt>co)continue;
                    D(a,n-now,0){
                        if(!g[a][k])continue;
                        int y=a+now;
                        int ci=1;ll base=inv[now];
                        for(;y<=n;ci++,y+=now,base=1ll*base*inv[now]%mod*inv[ci]%mod)
                            g[y][nxt]+=1ll*g[a][k]*base%mod,g[y][nxt]-=g[y][nxt]>=mod?mod:0;
                    }
                }
            }
            int t=1ll*p[rk[i]]*p[rk[i]]%mod;
            F(k,0,n)F(l,0,co)f[k][l]+=1ll*(g[k][l]-f[k][l]+mod)%mod*t%mod,f[k][l]-=f[k][l]>=mod?mod:0;
        }int ans=0;
        F(i,1,co)ans+=1ll*f[n][i]*nd[i]%mod*nd[i]%mod,ans-=ans>=mod?mod:0;
        pi(ans);
		return 0;
	}
}
signed main(){return EMT::main();}

序列问题

先用权值排序,用树状数组维护i-a[i]最长上升子序列即可。

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("sequence.in","r",stdin);freopen("sequence.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int N=5e5+10;
	struct node{int v1,v2,id;friend bool operator <(node a,node b){return a.v1==b.v1?a.v2>b.v2:a.v1<b.v1;}}p[N];
	int n,s[N],t[N],len;
	inline void add(int x,int v){while(x<=len)t[x]=max(t[x],v),x+=x&-x;}
	inline int ask(int x){int ans=0;while(x)ans=max(ans,t[x]),x-=x&-x;return ans;}
	inline short main(){
		file();
		n=read();
		F(i,1,n)
			p[i].v1=read(),s[i]=p[i].v2=i-p[i].v1,p[i].id=i;
		std::sort(s+1,s+n+1);
		len=std::unique(s+1,s+n+1)-s-1;
		F(i,1,n)p[i].v2=std::lower_bound(s+1,s+len+1,p[i].v2)-s;
		std::sort(p+1,p+n+1);
		F(i,1,n){
			if(p[i].v1>p[i].id)continue;
			int x=ask(p[i].v2);
			add(p[i].v2,x+1);
		}
		pi(ask(len));
		return 0;
	}
}
signed main(){return EMT::main();}

网格图

考虑只挪动一列的贡献不断变化即可。

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("grid.in","r",stdin);freopen("grid.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int N=510;
	int bian[N][N],fa[N*N],a[N][N],n,k,ans,pre[N][N],sum[N*N],id[N][N],cnt,siz[N*N];
	inline int getsum(int x,int y,int a,int b){
		return pre[a][b]-pre[x-1][b]-pre[a][y-1]+pre[x-1][y-1];
	}
	inline int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
	inline short main(){
		file();
		n=read(),k=read();
		F(i,1,n)F(j,1,n){
			char ch=getchar();bian[i][j]=++cnt;fa[bian[i][j]]=cnt,siz[cnt]=1;
			while(ch!='.'&&ch!='X')ch=getchar();
			a[i][j]=ch=='.'?1:0;pre[i][j]=pre[i-1][j]+pre[i][j-1]-pre[i-1][j-1]+a[i][j];
		}
		F(i,1,n)F(j,1,n)if(a[i][j]){
			int x=find(bian[i][j]);
			if(a[i+1][j]){
				int y=find(bian[i+1][j]);
				if(x!=y)
				fa[y]=x,siz[x]+=siz[y];
			}
			if(a[i][j+1]){
				int y=find(bian[i][j+1]);
				if(x!=y)
				fa[y]=x,siz[x]+=siz[y];
			}
		}
		F(i,1,n)F(j,1,n)id[i][j]=find(bian[i][j]);
		F(i,1,n-k+1){
			int now=0;
			F(j,i,i+k-1)F(l,1,k)if(a[j][l]){
				sum[id[j][l]]++;
				if(sum[id[j][l]]==1)now+=siz[id[j][l]];
			}
			F(l,i,i+k-1)if(a[l][k+1]){
				sum[id[l][k+1]]++;
				if(sum[id[l][k+1]]==1)now+=siz[id[l][k+1]];
			}
			F(l,1,k)if(a[i+k][l]){
				sum[id[i+k][l]]++;
				if(sum[id[i+k][l]]==1)now+=siz[id[i+k][l]];
			}
			F(l,1,k)if(a[i-1][l]){
				sum[id[i-1][l]]++;
				if(sum[id[i-1][l]]==1)now+=siz[id[i-1][l]];
			}
			ans=max(now-getsum(i,1,i+k-1,k),ans);
			F(j,k+1,n){
				F(l,i,i+k-1)if(a[l][j-k-1]){
					sum[id[l][j-k-1]]--;
					if(!sum[id[l][j-k-1]])now-=siz[id[l][j-k-1]];
				}
				F(l,i,i+k-1)if(a[l][j+1]){
					sum[id[l][j+1]]++;
					if(sum[id[l][j+1]]==1)now+=siz[id[l][j+1]];
				}
				if(a[i-1][j-k]){
					sum[id[i-1][j-k]]--;
					if(!sum[id[i-1][j-k]])now-=siz[id[i-1][j-k]];
				}
				if(a[i+k][j-k]){
					sum[id[i+k][j-k]]--;
					if(!sum[id[i+k][j-k]])now-=siz[id[i+k][j-k]];
				}
				if(a[i-1][j]){
					sum[id[i-1][j]]++;
					if(sum[id[i-1][j]]==1)now+=siz[id[i-1][j]];
				}
				if(a[i+k][j]){
					sum[id[i+k][j]]++;
					if(sum[id[i+k][j]]==1)now+=siz[id[i+k][j]];
				}ans=max(ans,now-getsum(i,j-k+1,i+k-1,j));
			}
			F(j,1,n)F(l,1,n)sum[id[j][l]]=0;
		}pi(ans+k*k);
		return 0;
	}
}
signed main(){return EMT::main();}

2021-09-28 19:28:45 星期二

过河

首先找各个三元组的公共部分,如果没有显然无解。然后枚举能删哪些点,将剩下的点连边记录经过一个点的奇环个数与最小的深度。
如果有一个点满足所有deep比它大的奇偶环最小深度都不全比它大则方案成立。

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("river.in","r",stdin);freopen("river.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int N=1e3+10;
	struct node{int next,to;}e[N*10];
	int p[N<<2][4];
	int n,m,king,deep[N],head[N],odd[N],f[N],co,Odd[N],Even[N],oddcnt;
	inline void add(int next,int to){e[++co]=(node){head[next],to};head[next]=co;}
	inline void dfs(int k,int fa){
		f[k]=fa;deep[k]=deep[fa]+1;
		for(register int i=head[k],j;i;i=e[i].next)if((j=e[i].to)!=fa){
			if(!deep[j]){
				dfs(j,k),odd[k]+=odd[j],Odd[k]=min(Odd[k],Odd[j]),Even[k]=min(Even[k],Even[j]);
			}else if(deep[j]<deep[k]&&((deep[k]-deep[j])&1)){
				Even[k]=min(Even[k],deep[j]);
			}else if(deep[j]<deep[k]&&!((deep[k]-deep[j])&1)){
				Odd[k]=min(Odd[k],deep[j]);
				odd[k]++;odd[f[j]]--;
				oddcnt++;
			}
		}
	}
	inline short main(){
		file();
		int T=read();
		while(T--){
			n=read(),m=read();
			F(i,1,m)p[i][1]=read(),p[i][2]=read(),p[i][3]=read();
			bool fl=0;
			F(i,1,3){
				bool flg=1;int x=p[1][i];
				F(j,2,m)if(p[j][1]!=x&&p[j][2]!=x&&p[j][3]!=x){flg=0;break;}
				if(flg){fl=1;king=x;break;}
			}
			if(!fl){puts("no");continue;}
			F(x,1,n){
				F(i,1,n)head[i]=deep[i]=odd[i]=f[i]=0,Odd[i]=Even[i]=1e9;co=0;oddcnt=0;fl=0;
				F(i,1,m){
					if(p[i][1]==king){
						if(p[i][2]==x||p[i][3]==x)continue;
						add(p[i][2],p[i][3]),
						add(p[i][3],p[i][2]);
					}else if(p[i][2]==king){
						if(p[i][1]==x||p[i][3]==x)continue;
						add(p[i][1],p[i][3]),
						add(p[i][3],p[i][1]);
					}else{
						if(p[i][2]==x||p[i][1]==x)continue;
						add(p[i][1],p[i][2]),
						add(p[i][2],p[i][1]);
					}
				}
				F(i,1,n)if(!deep[i]&&i!=king&&i!=x)dfs(i,0);
				F(i,1,n)if(odd[i]==oddcnt){
					int xx=1;
					for(register int j=head[i],k;j;j=e[j].next){
						k=e[j].to;
						if(deep[k]>deep[i]&&Odd[k]<deep[i]&&Even[k]<deep[i])xx=0;
					}fl|=xx;if(fl)break;
				}if(fl)break;
			}puts(fl?"yes":"no");
		}
		return 0;
	}
}
signed main(){return EMT::main();}

环路

建立矩阵快速幂把能连边的系数设成1,i和i+n,i+n和i+n都是1,最后出来的答案就是所有[i,i+n]的和-n。

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("tour.in","r",stdin);freopen("tour.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int N=110;
	int n,k,mod,a[N<<1][N<<1],b[N<<1][N<<1],c[N<<1][N<<1];
	inline char gc(){char ch=getchar();while(ch!='Y'&&ch!='N')ch=getchar();return ch;}
	inline void mul(int a[N<<1][N<<1],int b[N<<1][N<<1],int n){
		memset(c,0,sizeof(c));
		F(i,1,n)F(k,1,n)F(j,1,n)c[i][j]+=1ll*a[i][k]*b[k][j]%mod,c[i][j]-=c[i][j]>=mod?mod:0;
		F(i,1,n)F(j,1,n)a[i][j]=c[i][j];
	}
	inline short main(){
		file();
		n=read();
		F(i,1,n)F(j,1,n)if(gc()=='Y')a[i][j]=1;
		k=read(),mod=read();
		F(i,1,n)b[i][i]=a[i][i+n]=a[i+n][i+n]=1;
		while(k){
			if(k&1)mul(b,a,n*2);
			mul(a,a,n*2);k>>=1;
		}int ans=0;
		F(i,1,n)ans+=b[i][i+n],ans-=ans>=mod?mod:0;
		ans-=n;ans+=ans<0?mod:0;
		pi(ans);
		return 0;
	}
}
signed main(){return EMT::main();}

简单的字符串

使用hash+剪枝即可n3水过,好像开了O2卡不掉?

Code


#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	typedef unsigned long long ull;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("s.in","r",stdin);freopen("s.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int N=5100,bs=13331;
	int a[N],n,ans,pre[N];ull p[N],hash[N][N],hs[N];
	inline ull geths(int l,int r){return hs[r]-hs[l-1]*p[r-l+1];}
	inline bool check(int l,int r){
		int mid=(l+r)>>1,len=mid-l+1;
		ull hash1=geths(l,mid),hash2=geths(mid+1,r);
		if(hash1==hash2)return 1;
		F(i,l+1,mid){
			hash1=(hash1-a[i-1]*p[len-1])*13331+a[i-1];
			if(hash1==hash2)return 1;
		}return 0;
	}
	inline short main(){
		file();
		p[0]=1;n=read();
		F(i,1,n)a[i]=read(),pre[i]=pre[i-1]+a[i];F(i,1,5000)p[i]=p[i-1]*bs;
		//F(i,1,n)F(j,i,n)hash[i][j]=hash[i][j-1]+p[a[j]-1];
		F(i,1,n)hs[i]=hs[i-1]*13331+a[i];
		for(int len=2;len<=n;len+=2)
		F(i,1,n-len+1){
			int l=i,r=i+len-1,mid=(l+r)>>1;
			if(/*hash[l][mid]!=hash[mid+1][r]||*/pre[mid]-pre[l-1]!=pre[r]-pre[mid])continue;
			if(check(l,r))ans++;
		}pi(ans);
		return 0;
	}
}
signed main(){return EMT::main();}

三元组

使用常数较小的树状数组维护(1+\(i^2\),\(i\)+\(i^2\)),查询i的三次方即可。

Code


#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("exclaim.in","r",stdin);freopen("exclaim.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(ll x){pf("%lld ",x);}inline void pn(){pf("\n");}
	const int N=1e5+10;
	ll base;int n,k,t[N];
	inline void add(int x,int v){while(x<=k){t[x]+=v;x+=x&-x;}}
	inline int ask(int x){int ans=0;while(x){ans+=t[x],x-=x&-x;}return ans;}
	inline void change(int l,int r,int v){add(l,v),add(r+1,-v);}
	inline short main(){
		 file();
		int T=read(),co=0;
		while(T--){
			co++;
			F(i,1,k)t[i]=0;
			n=read(),k=read();
			ll ans=0;base=0;
			F(i,1,n){
				int x=(1+1ll*i*i%k)%k,y=(i+1ll*i*i%k)%k;
				if(x<=y)change(x+1,y+1,1);
				else change(x+1,k,1),change(1,y+1,1);
				base+=(i-1)/k;
				ans+=base+ask(1ll*i*i*i%k+1);
			}
			pf("Case %d: ",co);
			pi(ans);pn();
		}
		return 0;
	}
}
signed main(){return EMT::main();}

2021-09-27 21:01:49 星期一

排列

exx的题,24遍还不让复制黏贴...(%ycxjulao)

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<assert.h>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("c.in","r",stdin);freopen("c.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(ll x){pf("%lld ",x);}inline void pn(){pf("\n");}
	const int N=2005;
	int a[5],b[N],rt[N],n;ll ans;
	struct seg{
		int sum[N*40],tot,ls[N*40],rs[N*40];
		inline void insert(int x,int &y,int l,int r,int v){
			y=++tot;ls[y]=ls[x],rs[y]=rs[x];
			sum[y]=sum[x]+1;
			if(l==r)return;
			int mid=(l+r)>>1;
			if(v<=mid)insert(ls[x],ls[y],l,mid,v);
			else insert(rs[x],rs[y],mid+1,r,v);
		}
		inline int ask(int x,int y,int l,int r,int ql,int qr){
			if(ql>qr)return 0;
			if(!(sum[y]-sum[x]))return 0;
			if(l>=ql&&r<=qr)return sum[y]-sum[x];
			int mid=(l+r)>>1;
			if(qr<=mid)return ask(ls[x],ls[y],l,mid,ql,qr);
			if(ql>mid)return ask(rs[x],rs[y],mid+1,r,ql,qr);
			return ask(ls[x],ls[y],l,mid,ql,mid)+ask(rs[x],rs[y],mid+1,r,mid+1,qr);
		}
		inline void clear(){
			F(i,1,tot)sum[i]=ls[i]=rs[i]=0;
			F(i,1,n)rt[i]=0;
			tot=0;
		}
	}segm;
	inline void solve1(){
		F(i,2,n-2)F(j,i+1,n-1)if(b[j]>b[i]){
			int v1=segm.ask(rt[0],rt[i-1],1,n,1,b[i]-1),v2=segm.ask(rt[j],rt[n],1,n,b[j]+1,n);
			ans+=1ll*v1*v2;
		}pi(ans);
	}
	inline void solve2(){
		F(i,2,n-2)F(j,i+1,n-1)if(b[j]-b[i]>1){
			int v1=segm.ask(rt[0],rt[i-1],1,n,1,b[i]-1),v2=segm.ask(rt[j],rt[n],1,n,b[i]+1,b[j]-1);
			ans+=1ll*v1*v2;
		}pi(ans);
	}
	inline void solve3(){
		F(i,2,n-2)F(j,i+1,n-1)if(b[i]>b[j]){
			int v1=segm.ask(rt[0],rt[i-1],1,n,1,b[j]-1),v2=segm.ask(rt[j],rt[n],1,n,b[i]+1,n);
			ans+=1ll*v1*v2;
		}pi(ans);
	}
	inline void solve4(){
		F(i,2,n-2)F(j,i+2,n)if(b[i]>b[j]){
			int v1=segm.ask(rt[0],rt[i-1],1,n,1,b[j]-1),v2=segm.ask(rt[i],rt[j-1],1,n,b[i]+1,n);
			ans+=1ll*v1*v2;
		}pi(ans);
	}
	inline void solve5(){
		F(i,2,n-2)F(j,i+1,n)if(b[i]-b[j]>1){
			int v1=segm.ask(rt[0],rt[i-1],1,n,1,b[j]-1),v2=segm.ask(rt[j],rt[n],1,n,b[j]+1,b[i]-1);
			ans+=1ll*v1*v2;
		}pi(ans);
	}
	inline void solve6(){
		F(i,2,n-2)F(j,i+2,n)if(b[i]-b[j]>1){
			int v1=segm.ask(rt[0],rt[i-1],1,n,1,b[j]-1),v2=segm.ask(rt[i],rt[j-1],1,n,b[j]+1,b[i]-1);
			ans+=1ll*v1*v2;
		}pi(ans);
	}
	inline void solve7(){
		F(i,2,n-2)F(j,i+1,n-1)if(b[j]-b[i]>1){
			int v1=segm.ask(rt[0],rt[i-1],1,n,b[i]+1,b[j]-1),v2=segm.ask(rt[j],rt[n],1,n,b[j]+1,n);
			ans+=1ll*v1*v2;
		}pi(ans);
	}
	inline void solve8(){
		F(i,2,n-2)F(j,i+2,n)if(b[j]-b[i]>1){
			int v1=segm.ask(rt[0],rt[i-1],1,n,b[i]+1,b[j]-1),v2=segm.ask(rt[i],rt[j-1],1,n,b[j]+1,n);
			ans+=1ll*v1*v2;
		}pi(ans);
	}
	inline void solve9(){
		F(i,2,n-2)F(j,i+1,n-1)if(b[i]-b[j]>1){
			int v1=segm.ask(rt[0],rt[i-1],1,n,b[j]+1,b[i]-1),v2=segm.ask(rt[j],rt[n],1,n,b[i]+1,n);
			ans+=1ll*v1*v2;
		}pi(ans);
	}
	inline void solve10(){
		F(i,2,n-2)F(j,i+2,n)if(b[i]-b[j]>1){
			int v1=segm.ask(rt[0],rt[i-1],1,n,b[j]+1,b[i]-1),v2=segm.ask(rt[i],rt[j-1],1,n,b[i]+1,n);
			ans+=1ll*v1*v2;
		}pi(ans);
	}
	inline void solve11(){
		F(i,4,n){
			int sum=0,key=1;
			while(key<i){
				if(b[key]>b[i])ans+=sum;
				else{
					sum-=segm.ask(rt[0],rt[key-1],1,n,b[key]+1,b[i]-1);
					sum+=segm.ask(rt[key],rt[i-1],1,n,1,b[key]-1);
				}key++;
			}
		}pi(ans);
	}
	inline void solve12(){
		F(i,1,n-3)F(j,i+2,n-1)if(b[i]<b[j]){
			int v1=segm.ask(rt[i],rt[j-1],1,n,b[j]+1,n),v2=segm.ask(rt[j],rt[n],1,n,1,b[i]-1);
			ans+=1ll*v1*v2;
		}pi(ans);
	}
	inline void solve13(){
		F(i,1,n-3)F(j,i+2,n-1)if(b[i]>b[j]){
			int v1=segm.ask(rt[i],rt[j-1],1,n,1,b[j]-1),v2=segm.ask(rt[j],rt[n],1,n,b[i]+1,n);
			ans+=1ll*v1*v2;
		}pi(ans);
	}
	inline void solve14(){
		std::reverse(b+1,b+n+1);
		segm.clear();
		F(i,1,n)segm.insert(rt[i-1],rt[i],1,n,b[i]);
		solve11();
	}
	inline void solve15(){
		F(i,1,n-3)F(j,i+2,n-1)if(b[i]-b[j]>1){
			int v1=segm.ask(rt[i],rt[j-1],1,n,b[j]+1,b[i]-1),v2=segm.ask(rt[j],rt[n],1,n,b[i]+1,n);
			ans+=1ll*v1*v2;
		}pi(ans);
	}
	inline void solve16(){
		F(i,2,n-2)F(j,i+1,n-1)if(b[j]-b[i]>1){
			int v1=segm.ask(rt[0],rt[i-1],1,n,b[i]+1,b[j]-1),v2=segm.ask(rt[j],rt[n],1,n,1,b[i]-1);
			ans+=1ll*v1*v2;
		}pi(ans);
	}
	inline void solve17(){
		F(i,1,n-3)F(j,i+2,n-1)if(b[i]-b[j]>1){
			int v1=segm.ask(rt[i],rt[j-1],1,n,b[i]+1,n),v2=segm.ask(rt[j],rt[n],1,n,b[j]+1,b[i]-1);
			ans+=1ll*v1*v2;
		}pi(ans);
	}
	inline void solve18(){
		F(i,1,n-3)F(j,i+2,n-1)if(b[i]>b[j]){
			int v1=segm.ask(rt[i],rt[j-1],1,n,b[i]+1,n),v2=segm.ask(rt[j],rt[n],1,n,1,b[j]-1);
			ans+=1ll*v1*v2;
		}pi(ans);
	}
	inline void solve19(){
		F(i,1,n-3)F(j,i+2,n-1)if(b[i]-b[j]>1){
			int v1=segm.ask(rt[i],rt[j-1],1,n,1,b[j]-1),v2=segm.ask(rt[j],rt[n],1,n,b[j]+1,b[i]-1);
			ans+=1ll*v1*v2;
		}pi(ans);
	}
	inline void solve20(){
		F(i,2,n-2)F(j,i+1,n-1)if(b[j]-b[i]>1){
			int v1=segm.ask(rt[0],rt[i-1],1,n,b[j]+1,n),v2=segm.ask(rt[j],rt[n],1,n,b[i]+1,b[j]-1);
			ans+=1ll*v1*v2;
		}pi(ans);
	}
	inline void solve21(){
		F(i,2,n-2)F(j,i+2,n)if(b[j]>b[i]){
			int v1=segm.ask(rt[0],rt[i-1],1,n,b[j]+1,n),v2=segm.ask(rt[i],rt[j-1],1,n,1,b[i]-1);
			ans+=1ll*v1*v2;
		}pi(ans);
	}
	inline void solve22(){
		F(i,2,n-2)F(j,i+1,n-1)if(b[j]>b[i]){
			int v1=segm.ask(rt[0],rt[i-1],1,n,b[j]+1,n),v2=segm.ask(rt[j],rt[n],1,n,1,b[i]-1);
			ans+=1ll*v1*v2;
		}pi(ans);
	}
	inline void solve23(){
		F(i,2,n-2)F(j,i+1,n-1)if(b[i]-b[j]>1){
			int v1=segm.ask(rt[0],rt[i-1],1,n,b[i]+1,n),v2=segm.ask(rt[j],rt[n],1,n,b[j]+1,b[i]-1);
			ans+=1ll*v1*v2;
		}pi(ans);
	}
	inline void solve24(){
		F(i,2,n-2)F(j,i+1,n-1)if(b[i]>b[j]){
			int v1=segm.ask(rt[0],rt[i-1],1,n,b[i]+1,n),v2=segm.ask(rt[j],rt[n],1,n,1,b[j]-1);
			ans+=1ll*v1*v2;
		}pi(ans);
	}
	inline short main(){
		file();
		n=read();
		F(i,1,4)a[i]=read();
		F(i,1,n)b[i]=read(),segm.insert(rt[i-1],rt[i],1,n,b[i]);
		if(a[1]==1&&a[2]==2&&a[3]==3&&a[4]==4)solve1();
		if(a[1]==1&&a[2]==2&&a[3]==4&&a[4]==3)solve2();
		if(a[1]==1&&a[2]==3&&a[3]==2&&a[4]==4)solve3();
		if(a[1]==1&&a[2]==3&&a[3]==4&&a[4]==2)solve4();
		if(a[1]==1&&a[2]==4&&a[3]==2&&a[4]==3)solve5();
		if(a[1]==1&&a[2]==4&&a[3]==3&&a[4]==2)solve6();
		if(a[1]==2&&a[2]==1&&a[3]==3&&a[4]==4)solve7();
		if(a[1]==2&&a[2]==1&&a[3]==4&&a[4]==3)solve8();
		if(a[1]==2&&a[2]==3&&a[3]==1&&a[4]==4)solve9();
		if(a[1]==2&&a[2]==3&&a[3]==4&&a[4]==1)solve10();
		if(a[1]==2&&a[2]==4&&a[3]==1&&a[4]==3)solve11();
		if(a[1]==2&&a[2]==4&&a[3]==3&&a[4]==1)solve12();
		if(a[1]==3&&a[2]==1&&a[3]==2&&a[4]==4)solve13();
		if(a[1]==3&&a[2]==1&&a[3]==4&&a[4]==2)solve14();
		if(a[1]==3&&a[2]==2&&a[3]==1&&a[4]==4)solve15();
		if(a[1]==3&&a[2]==2&&a[3]==4&&a[4]==1)solve16();
		if(a[1]==3&&a[2]==4&&a[3]==1&&a[4]==2)solve17();
		if(a[1]==3&&a[2]==4&&a[3]==2&&a[4]==1)solve18();
		if(a[1]==4&&a[2]==1&&a[3]==2&&a[4]==3)solve19();
		if(a[1]==4&&a[2]==1&&a[3]==3&&a[4]==2)solve20();
		if(a[1]==4&&a[2]==2&&a[3]==1&&a[4]==3)solve21();
		if(a[1]==4&&a[2]==2&&a[3]==3&&a[4]==1)solve22();
		if(a[1]==4&&a[2]==3&&a[3]==1&&a[4]==2)solve23();
		if(a[1]==4&&a[2]==3&&a[3]==2&&a[4]==1)solve24();
		return 0;
	}
}
signed main(){return EMT::main();}

电压机制

发现如果有大于等于2个奇环那么所有返祖边都不合法,否则一定合法,判一下哪些边被所有奇环所包括即可。

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("a.in","r",stdin);freopen("a.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int N=1e5+10,inf=1e9;
	int co=1,head[N],sum[N];
	struct node{int from,next,to,w;}e[N<<2];
	inline void add(int next,int to){e[++co]=(node){next,head[next],to,0};head[next]=co;}
	int n,m,deep[N],tot;bool vis[N];ll odd[N];
	inline void dfs1(int k){
		vis[k]=1;
		for(register int i=head[k],j;i;i=e[i].next)if(!vis[j=e[i].to]){
			e[i].w=e[i^1].w=1;
			deep[j]=deep[k]+1;vis[j]=1;
			dfs1(j);
		}
	}
	inline void dfs2(int k,int fa){
		for(register int i=head[k],j;i;i=e[i].next)if(e[i].w){
			if(e[i].to==fa)continue;
			j=e[i].to;dfs2(j,k);
		}else{
			j=e[i].to;
			if(deep[j]>deep[k])continue;
			if((deep[k]-deep[j])&1){
				odd[k]-=inf;
				odd[j]+=inf;
			}else odd[k]++,odd[j]--,tot++;
		}
	}int ans;
	inline void dfs3(int k,int fa){
		for(register int i=head[k],j;i;i=e[i].next)if(e[i].w){
			j=e[i].to;
			if(deep[j]<deep[k])continue;
			dfs3(j,k);odd[k]+=odd[j];
		}sum[k]+=odd[k];if(sum[k]==tot&&k!=1)ans++;
	}
	inline short main(){
		file();
		n=read(),m=read();
		F(i,1,m){
			int x=read(),y=read();
			add(x,y),add(y,x);
		}
		dfs1(1);
		dfs2(1,0);
		dfs3(1,0);
		pi(tot==1?ans+1:ans);
		return 0;
	}
}
signed main(){return EMT::main();}

题目难度提升

模拟题,就是求中位数有点麻烦,所以建两棵权值线段树分别代表现役和预备役即可。

Code


#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("d.in","r",stdin);freopen("d.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int N=1e5+10;int rt[5],n,a[N];
	struct seg{
		int tot,siz[N*40],ls[N*40],rs[N*40],maxval[N*40];//1预备役 2现役
		inline void change(int &p,int l,int r,int x,int v){
			if(!p)p=++tot;
			siz[p]+=v;
			if(l==r){if(siz[p])maxval[p]=l;else maxval[p]=0;return;}int mid=(l+r)>>1;
			if(x<=mid)change(ls[p],l,mid,x,v);
			else change(rs[p],mid+1,r,x,v);
			maxval[p]=max(maxval[ls[p]],maxval[rs[p]]);
		}
		inline int kth(int p,int l,int r,int x){
			if(!p)return 0;
			if(l==r)return l;
			int mid=(l+r)>>1;
			if(x>siz[ls[p]])return kth(rs[p],mid+1,r,x-siz[ls[p]]);
			else return kth(ls[p],l,mid,x);
		}
		inline int findst(int p,int l,int r,int x,int now){
			if(l==r)return siz[p]?now:now+1;
			int mid=(l+r)>>1;
			if(x>mid)return findst(rs[p],mid+1,r,x,now+siz[ls[p]]);
			else return findst(ls[p],l,mid,x,now);
		}
		inline int finded(int p,int l,int r,int x,int now){
			if(l==r)return siz[p]?now+siz[p]-1:now;
			int mid=(l+r)>>1;
			if(x>mid)return finded(rs[p],mid+1,r,x,now+siz[ls[p]]);
			else return finded(ls[p],l,mid,x,now);
		}
		inline int getmax(int p,int l,int r,int ql,int qr){
			if(!p)return 0;
			if(l>=ql&&r<=qr)return maxval[p];
			int mid=(l+r)>>1;
			if(qr<=mid)return getmax(ls[p],l,mid,ql,qr);
			if(ql>mid)return getmax(rs[p],mid+1,r,ql,qr);
			return max(getmax(ls[p],l,mid,ql,mid),getmax(rs[p],mid+1,r,mid+1,qr));
		}
	}segm;
	int mid;
	inline void move(int x){
		pi(x);
		segm.change(rt[2],1,1e9,x,1);
		segm.change(rt[1],1,1e9,x,-1);
	}
	inline void solve1(){
		F(i,1,n)segm.change(rt[1],1,1e9,a[i],1);
		int x=segm.kth(1,1,1e9,1);mid=x;
		move(x);
		while(segm.siz[rt[1]]>1){
			mid=segm.kth(rt[2],1,1e9,segm.siz[rt[2]]/2+1);
			int k=segm.kth(rt[1],1,1e9,segm.finded(rt[1],1,1e9,mid,0)+1);
			if(mid+1>k-1||!segm.getmax(rt[2],1,1e9,mid+1,k-1)){
				int R=2*k-mid;
				if(!segm.getmax(rt[2],1,1e9,mid+1,R))move(segm.getmax(rt[1],1,1e9,mid+1,R));
				else move(segm.maxval[rt[1]]);
			}else move(segm.maxval[rt[1]]);
			db M=(db)(segm.kth(rt[2],1,1e9,segm.siz[rt[2]]/2)+segm.kth(rt[2],1,1e9,segm.siz[rt[2]]/2+1))/2.0;
			bool fl=0;
			if(M-floor(M)>=0.4&&M-floor(M)<=0.6)fl=1;//fl表示.5
			int L;
			if(fl){
				mid=ceil(M);int kth=segm.findst(1,1,1e9,mid,0);
				L=segm.kth(rt[1],1,1e9,kth);
				if(L<M)L=segm.kth(rt[1],1,1e9,kth+1);
			}else{
				mid=M;
				int kth=segm.findst(1,1,1e9,mid,0);
				L=segm.kth(rt[1],1,1e9,kth);
				if(L<M)L=segm.kth(rt[1],1,1e9,kth+1);
			}if(fl)mid--;
			if(mid+1>L-1||!segm.getmax(rt[2],1,1e9,mid+1,L-1))move(L);
			else move(segm.maxval[rt[1]]);
		}if(segm.siz[rt[1]])move(segm.maxval[rt[1]]);
	}
	int last=-1,cf=0;
	inline void solve2(){
		F(i,1,n)segm.change(rt[1],1,1e9,a[i],1);
		move(cf);move(cf);
		while(segm.siz[rt[1]]>1){
			int x=segm.getmax(rt[1],1,1e9,1,cf);
			if(!x)break;
			move(segm.maxval[rt[1]]);
			x=segm.getmax(rt[1],1,1e9,1,cf);
			move(x);
		}
		if(!segm.siz[rt[1]])return;
		move(segm.maxval[rt[1]]);
		while(segm.siz[rt[1]]>1){
			mid=segm.kth(rt[2],1,1e9,segm.siz[rt[2]]/2+1);
			int k=segm.kth(rt[1],1,1e9,segm.finded(rt[1],1,1e9,mid,0)+1);
			if(mid+1>k-1||!segm.getmax(rt[2],1,1e9,mid+1,k-1)){
				int R=2*k-mid;
				if(!segm.getmax(rt[2],1,1e9,mid+1,R))move(segm.getmax(rt[1],1,1e9,mid+1,R));
				else move(segm.maxval[rt[1]]);
			}else move(segm.maxval[rt[1]]);
			db M=(db)(segm.kth(rt[2],1,1e9,segm.siz[rt[2]]/2)+segm.kth(rt[2],1,1e9,segm.siz[rt[2]]/2+1))/2.0;
			bool fl=0;
			if(M-floor(M)>=0.4&&M-floor(M)<=0.6)fl=1;//fl表示.5
			int L;
			if(fl){
				mid=ceil(M);int kth=segm.findst(1,1,1e9,mid,0);
				L=segm.kth(rt[1],1,1e9,kth);
				if(L<M)L=segm.kth(rt[1],1,1e9,kth+1);
			}else{
				mid=M;
				int kth=segm.findst(1,1,1e9,mid,0);
				L=segm.kth(rt[1],1,1e9,kth);
				if(L<M)L=segm.kth(rt[1],1,1e9,kth+1);
			}if(fl)mid--;
			if(mid+1>L-1||!segm.getmax(rt[2],1,1e9,mid+1,L-1))move(L);
			else move(segm.maxval[rt[1]]);
		}if(segm.siz[rt[1]])move(segm.maxval[rt[1]]);
	}
	inline short main(){
		file();
		n=read();
		F(i,1,n)a[i]=read();
		std::sort(a+1,a+n+1);
		if(n&1){
			D(i,n,1){
				if(last==a[i]&&i<=n/2+1){
					cf=a[i];
					break;
				}last=a[i];
			}
		}else{
			D(i,n,1){
				if(last==a[i]&&i<=n/2){
					cf=a[i];
					break;
				}last=a[i];
			}
		}
		if(!cf)solve1();
		else solve2();
		return 0;
	}
}
signed main(){return EMT::main();}


题目交流通道

发现d=0的路径将整张图连成了几个团,于是用并查集判一下将答案乘起来即可。

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define int long long
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("c.in","r",stdin);freopen("c.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int N=410,mod=998244353;
	int d[N][N],n,k,jc[N],inv[N],f[N],g[N],fa[N],cnt[N][N],dis[N][N],ans=1,siz[N];bool vis[N][N],vi[N];
	inline int ksm(int a,int b){int ans=1;while(b){if(b&1)ans=1ll*a*ans%mod;a=1ll*a*a%mod;b>>=1;}return ans;}
	inline int C(int n,int m){return 1ll*jc[n]*inv[m]%mod*inv[n-m]%mod;}
	inline int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
	inline short main(){
		file();
		n=read(),k=read();jc[0]=inv[0]=inv[1]=1;
		F(i,1,n)F(j,1,n)d[i][j]=read();
		F(i,1,n)F(j,1,n){if(d[i][j]>k||d[i][j]!=d[j][i])puts("0"),exit(0);
		F(k,1,n)if(d[i][j]>d[i][k]+d[k][j])puts("0"),exit(0);}
		F(i,1,n)jc[i]=1ll*jc[i-1]*i%mod;
		inv[n]=ksm(jc[n],mod-2);
		D(i,n-1,2)inv[i]=1ll*(i+1)*inv[i+1]%mod;
		g[1]=f[1]=1;
		F(i,2,n)g[i]=ksm(k+1,C(i,2));
		F(i,2,n){f[i]=g[i];F(j,1,i-1)f[i]-=1ll*f[j]*g[i-j]%mod*C(i-1,j-1)%mod*ksm(k,j*(i-j))%mod,f[i]+=f[i]<0?mod:0;}
		F(i,1,n)fa[i]=i,siz[i]=1;
		F(i,1,n)F(j,i+1,n){
			if(!d[i][j]){
				int fx=find(i),fy=find(j);
				if(fx!=fy)fa[fy]=fx,siz[fx]+=siz[fy];
			}
		}
		F(i,1,n){
			int fx=find(i);
			if(vi[fx])continue;vi[fx]=1;
			ans=1ll*ans*f[siz[fx]]%mod;
		}
		F(i,1,n)F(j,i+1,n){int fx=find(i),fy=find(j);cnt[fx][fy]++;cnt[fy][fx]++;dis[fx][fy]=dis[fy][fx]=d[i][j];}
		F(i,1,n)F(j,i+1,n){
			int fx=find(i),fy=find(j);
			if(vis[fx][fy]||fx==fy)continue;
			vis[fx][fy]=vis[fy][fx]=1;bool fl=0;
			F(k,1,n)if(k!=fx&&k!=fy&&dis[fx][fy]==dis[fx][k]+dis[k][fy]){fl=1;break;}
			if(fl)ans=1ll*ans*ksm(k-dis[fx][fy]+1,cnt[fx][fy])%mod;
			else ans=1ll*ans*((ksm(k-dis[fx][fy]+1,cnt[fx][fy])-ksm(k-dis[fx][fy],cnt[fx][fy])+mod)%mod)%mod;
		}pi(ans);
		return 0;
	}
}
signed main(){return EMT::main();}

Read

统计出最多的点是哪个检验一下是否大于n/2+1即可。

Code


#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<map>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("b.in","r",stdin);freopen("b.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	int x[1100],y[1100],z[1100],count[1100],m,k,now=-1,cnt,n;
	std::map<int,int>mp;
	inline bool com(int i,int j){return i>j;}
	inline short main(){
		file();
		m=read(),k=read();
		F(i,1,m)count[i]=read(),n+=count[i];
		F(i,1,m)x[i]=read();
		F(i,1,m)y[i]=read();
		F(i,1,m)z[i]=read();
		int s=(1<<k)-1,dp;
		F(i,1,m){
			dp=x[i];
			if(!cnt)now=dp,cnt=1;
			else if(now==dp)cnt++;
			else cnt--;
			ll last=dp;
			F(j,1,count[i]-1){
				last=(last*y[i]+z[i])&s;
				dp=last;
				if(!cnt)now=dp,cnt=1;
				else if(now==dp)cnt++;
				else cnt--;
			}
		}
		cnt=0;
		F(i,1,m){
			dp=x[i];
			if(now==dp)cnt++;
			ll last=dp;
			F(j,1,count[i]-1){
				last=(last*y[i]+z[i])&s;
				dp=last;
				if(now==dp)cnt++;
			}
		}
		if(cnt<=(n+1)/2)pi(0);
		else{
			int rest=n-cnt;
			n-=rest*2+1;
			pi(n);
		}
		return 0;
	}
}
signed main(){return EMT::main();}

Set

发现如果序列中没有零一定有重复的前缀和,一减就行。

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("a.in","r",stdin);freopen("a.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int N=1e6+10;
	int n,last[N],pre[N];
	inline short main(){
		file();
		n=read();
		F(i,1,n){
			pre[i]=(read()%n+pre[i-1])%n;
			if(last[pre[i]]){
				pi(i-last[pre[i]]);
				F(j,last[pre[i]]+1,i)pi(j);
				return 0;
			}last[pre[i]]=i;
		}
		return 0;
	}
}
signed main(){return EMT::main();}

2021-09-25 20:52:27 星期六

花瓶

对点进行斜率优化,斜率是f数组之差与pre数组之差的比值,为了不爆精度移到两边相乘即可。

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("d.in","r",stdin);freopen("d.out","w",stdout);}
	inline ll max(ll a,ll b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(ll x){pf("%lld ",x);}inline void pn(){pf("\n");}
	const int N=5100;
	ll pre[N],f[N][N];int n,p[N],q[N],hd,tl,rec1[N],co1,rec2[N],co2;
	inline bool com(int i,int j){return pre[i]>pre[j];}
	inline db lop(int k,int kk,int j){return (db)(f[j][k]-f[j][kk])/(db)(pre[k]-pre[kk]);}
	inline bool lopp(int k,int kk,int kkk,int j){
		if(pre[k]-pre[kk]<0){
			if(pre[kkk]-pre[kk]<0){
				return 1ll*(f[j][k]-f[j][kk])*(pre[kkk]-pre[kk])<=1ll*(f[j][kkk]-f[j][kk])*(pre[k]-pre[kk]);
			}else return 1ll*(f[j][k]-f[j][kk])*(pre[kkk]-pre[kk])>=1ll*(f[j][kkk]-f[j][kk])*(pre[k]-pre[kk]);
		}else{
			if(pre[kkk]-pre[kk]<0){
				return 1ll*(f[j][k]-f[j][kk])*(pre[kkk]-pre[kk])>=1ll*(f[j][kkk]-f[j][kk])*(pre[k]-pre[kk]);
			}else return 1ll*(f[j][k]-f[j][kk])*(pre[kkk]-pre[kk])<=1ll*(f[j][kkk]-f[j][kk])*(pre[k]-pre[kk]);
		}
	}
	inline short main(){
		file();
		n=read();
		F(i,1,n)pre[i]=pre[i-1]+read();
		F(i,2,n)F(j,1,i-1)f[i][j]=-1e18;
		F(i,1,n)p[i]=i;
		std::sort(p+0,p+n+1,com);
		F(i,1,n-1){
			// pf("Case %d:\n",i);
			co1=co2=0;hd=1;tl=0;
			D(j,n,0)if(p[j]<i)rec1[++co1]=p[j];
			F(j,0,n)if(p[j]>i)rec2[++co2]=p[j];
			F(j,1,co1){
				while(hd<tl&&/*lop(q[tl],q[tl-1],i)<=lop(rec1[j],q[tl-1],i)*/lopp(q[tl],q[tl-1],rec1[j],i))tl--;
				q[++tl]=rec1[j];
			}
			// F(j,hd,tl)pi(j-hd+1),pi(q[j]),pi(f[i][q[j]]),pi(pre[q[j]]),pn();
			// pf("\n\nchange:\n");
			F(j,1,co2){
				while(hd<tl&&((pre[q[hd+1]]==pre[q[hd]]&&f[i][q[hd]]<=f[i][q[hd+1]])||lop(q[hd+1],q[hd],i)>=pre[rec2[j]]-pre[i]))hd++;
				f[rec2[j]][i]=f[i][q[hd]]+1ll*(pre[i]-pre[q[hd]])*(pre[rec2[j]]-pre[i]);
				// pi(rec2[j]);pi(i);pi(q[hd]);pi(f[rec2[j]][i]);pi(f[i][q[hd]]);pn();
			}//pn();pn();
		}ll ans=0;
		F(i,0,n)ans=max(ans,f[n][i]);
		pi(ans);
		return 0;
	}
}
signed main(){return EMT::main();}

矩阵

考虑到一个3x3的矩形中上左、中右、下中的和与上中、中左、右下的相反数之和不变,所以若有任意一个3x3矩形和不为0则不合法否则合法,判完模拟即可。

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("c.in","r",stdin);freopen("c.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(ll x){pf("%lld ",x);}inline void pn(){pf("\n");}
	int n,m;ll a[1100][1100],ans[6100][3];
	inline short main(){
		file();
		n=read(),m=read();
		F(i,1,n)F(j,1,m)a[i][j]=read();
		F(i,1,n-2)F(j,1,m-2)if(a[i][j]-a[i][j+1]-a[i+1][j]+a[i+1][j+2]+a[i+2][j+1]-a[i+2][j+2]!=0){pi(-1);return 0;}
		if(n==2){
			pi(m*2);pn();
			F(i,1,m){
				pi(2);pi(i);pi(-a[2][i]);pn();
				a[1][i]-=a[2][i];
				pi(3);pi(i-1);pi(-a[1][i]);pn();
				a[2][i+1]-=a[1][i];
			}
			return 0;
		}else{
			int cnt=0;
			D(i,m,2){
				ans[++cnt][0]=2;ans[cnt][1]=i;ans[cnt][2]=-a[1][i];
				a[2][i]-=a[1][i];
				ans[++cnt][0]=3;ans[cnt][1]=i-2;ans[cnt][2]=-a[2][i];
				a[1][i-1]-=a[2][i];
			}
			D(i,n,1)a[i][2]-=a[1][2];
			ans[++cnt][0]=2;ans[cnt][1]=1;ans[cnt][2]=-a[1][1];
			D(i,n,1)a[i][1]-=a[1][1];
			F(i,2,n-1){
				ans[++cnt][0]=3;ans[cnt][1]=1-i;ans[cnt][2]=-a[i][1];
				a[i+1][2]-=a[i][1];
				ans[++cnt][0]=1;ans[cnt][1]=i+1;ans[cnt][2]=-a[i+1][2];
				a[i+1][1]-=a[i+1][2];
			}
			ans[++cnt][0]=3;ans[cnt][1]=1-n;ans[cnt][2]=-a[n][1];
			pi(cnt);
			F(i,1,cnt){F(j,0,2)pi(ans[i][j]);pn();}
		}
		return 0;
	}
}
signed main(){return EMT::main();}

小P的单调数列

最优策略一定只有一段或两段,用权值线段树维护即可。

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("b.in","r",stdin);freopen("b.out","w",stdout);}
	inline ll max(ll a,ll b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(db x){pf("%.3lf ",x);}inline void pn(){pf("\n");}
	const int N=1e5+10;
	struct seg{
		ll val[N<<2];
		inline void change(int p,int l,int r,int x,ll v){
			if(l==r){val[p]=max(val[p],v);return;}
			int mid=(l+r)>>1;
			if(x<=mid)change(p<<1,l,mid,x,v);
			else change(p<<1|1,mid+1,r,x,v);
			val[p]=max(val[p<<1],val[p<<1|1]);
		}
		inline ll ask(int p,int l,int r,int ql,int qr){
			if(l>=ql&&r<=qr)return val[p];
			int mid=(l+r)>>1;
			if(qr<=mid)return ask(p<<1,l,mid,ql,qr);
			if(ql>mid)return ask(p<<1|1,mid+1,r,ql,qr);
			return max(ask(p<<1,l,mid,ql,mid),ask(p<<1|1,mid+1,r,mid+1,qr));
		}
	}segm[2];//0上升,1下降。
	int n,a[N],s[N];
	inline short main(){
		file();
		n=read();
		F(i,1,n)s[i]=a[i]=read();
		std::sort(s+1,s+n+1);
		int len=std::unique(s+1,s+n+1)-s-1;
		F(i,1,n)a[i]=std::lower_bound(s+1,s+len+1,a[i])-s;
		F(i,1,n){
			if(a[i]>1){
				ll v1=segm[0].ask(1,1,len,1,a[i]-1);
				segm[0].change(1,1,len,a[i],v1+s[a[i]]);
				if(a[i]<len){
					ll v2=segm[0].ask(1,1,len,a[i]+1,len),v3=segm[1].ask(1,1,len,a[i]+1,len);
					if(max(v2,v3))segm[1].change(1,1,len,a[i],max(v2,v3)+s[a[i]]);
				}
			}else{
				ll v1=segm[0].ask(1,1,len,a[i]+1,len),v2=segm[1].ask(1,1,len,a[i]+1,len);
				if(max(v1,v2))segm[1].change(1,1,len,a[i],max(v2,v1)+s[a[i]]);
				segm[0].change(1,1,len,a[i],s[a[i]]);
			}
		}
		db v1=segm[0].val[1],v2=1.0*segm[1].val[1]/2.0;
		pi(v1>v2?v1:v2);
		return 0;
	}
}
signed main(){return EMT::main();}

交通

将边化为点,点化为边,两个出边和两个入边连边,求图中环的个数即可。

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace emt{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int mod=998244353,N=1e5+10;
	inline int ksm(int a,int b){
		int ans=1;
		while(b){
			if(b&1)ans=1ll*a*ans%mod;
			a=1ll*a*a%mod;b>>=1;
		}return ans;
	}
	int head[N<<1],co,fa[N<<1],n;
	struct node{int next,to;}e[N<<2];
	inline void add(int next,int to){e[++co]=(node){head[next],to};head[next]=co;}
	int cnt;bool vis[N<<1];
	inline void dfs(int k){
		vis[k]=1;
		for(register int i=head[k];i;i=e[i].next)
			if(!vis[e[i].to])dfs(e[i].to);
	}
	inline void solve(){
		F(i,1,n)if(!vis[i]){cnt++;dfs(i);}
		pi(ksm(2,cnt));
	}
	inline short main(){
		solve();
		return 0;
	}
}
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("a.in","r",stdin);freopen("a.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int mod=998244353,N=1e5+10;
	inline int ksm(int a,int b){
		int ans=1;
		while(b){
			if(b&1)ans=1ll*a*ans%mod;
			a=1ll*a*a%mod;b>>=1;
		}return ans;
	}int in[N][3],out[N][3],n;
	struct node{int from,to,id;}e[N<<1];
	inline short main(){
		file();
		n=read();
		F(i,1,n<<1){
			e[i].from=read(),e[i].to=read(),e[i].id=i;
			in[e[i].to][++in[e[i].to][0]]=i;
			out[e[i].from][++out[e[i].from][0]]=i;
		}
		F(i,1,n)emt::add(out[i][1],out[i][2]),emt::add(out[i][2],out[i][1]);
		F(i,1,n)emt::add(in[i][1],in[i][2]),emt::add(in[i][2],in[i][1]);
		emt::n=n*2;emt::main();
		return 0;
	}
}
signed main(){return EMT::main();}

2021-09-23 19:49:01 星期四

糖果

考虑到矩阵快速幂做m次转移,初状态是\(f_m=1\)答案就是\(f_0\)

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline ll read(){ll x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("sugar.in","r",stdin);freopen("sugar.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int N=1e7+10,mod=998244353;
	int w[110][110][110],b[110][110],c[110],d[110];
	int m,val[N<<1],A,B,P,last[N],jc[110],inv[110];ll n,tim[110];
	inline void mul(int a[110],int b[110][110]){
		memset(d,0,sizeof(d));
		F(i,0,m)F(j,0,m)(d[i]+=1ll*a[j]*b[j][i]%mod)%=mod;
		F(i,0,m)a[i]=d[i];
	}
	inline void muls(int a[110][110]){
		memset(b,0,sizeof(b));
		F(i,0,m)F(k,0,m)F(j,0,m)(b[i][j]+=1ll*a[i][k]*a[k][j]%mod)%=mod;
		F(i,0,m)F(j,0,m)a[i][j]=b[i][j];
	}
	inline int ksm(int a,int b){
		int ans=1;
		while(b){
			if(b&1)ans=1ll*a*ans%mod;
			b>>=1;a=1ll*a*a%mod;
		}return ans;
	}
	inline int C(int n,int m){
		return 1ll*jc[n]*inv[m]%mod*inv[n-m]%mod;
	}
	inline void init(){
		jc[0]=1;
		F(i,1,m)jc[i]=1ll*jc[i-1]*i%mod;
		inv[0]=inv[1]=1;inv[m]=ksm(jc[m],mod-2);
		D(i,m-1,2)inv[i]=1ll*(i+1)*inv[i+1]%mod;
		c[m]=1;
		F(i,1,m){
			F(j,0,m){
				D(k,j,0){
					if(j-k>i)break;
					w[i][j][k]=C(j,j-k);
				}
			}
			while(tim[i]){
				if(tim[i]&1)mul(c,w[i]);
				muls(w[i]);tim[i]>>=1;
			}
		}
		pi(c[0]);
	}
	inline short main(){
		file();
		n=read(),m=read();
		val[1]=read();last[val[1]]=1;A=read(),B=read(),P=read();
		int st=1,ed=n,len;
		F(i,2,n){
			val[i]=(1ll*val[i-1]*A%P+B)%P+1;
			if(last[val[i]]){st=i;break;}
			last[val[i]]=i;
		}
		memset(last,0,sizeof(last));
		last[val[st]]=st;
		F(i,st+1,n){

			val[i]=(1ll*val[i-1]*A%P+B)%P+1;
			if(last[val[i]]){ed=i-1;break;}
			last[val[i]]=i;
		}len=ed-st+1;
		F(i,1,st-1){
			if(val[i]>m)tim[m]++;
			else tim[val[i]]++;
		}n-=st-1;
		F(i,st,ed){
			if(val[i]>m)tim[m]+=n/len;
			else tim[val[i]]+=n/len;
		}
		n-=1ll*(n/len)*len;
		F(i,st,st+n-1){
			if(val[i]>m)tim[m]++;
			else tim[val[i]]++;
		}
		init();
		return 0;
	}
}
signed main(){return EMT::main();}

整除

等价于求\(x^m\equiv x(mod\ c_i)\)于是可以积性筛出\(x^m\)求解即可。

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("division.in","r",stdin);freopen("division.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int N=1e4+10;
	int pw[N],c,m,prime[N],co;bool vis[N];
	inline int ksm(int a,int b,int mod){
		int ans=1;
		while(b){
			if(b&1)ans=1ll*a*ans%mod;
			a=1ll*a*a%mod;b>>=1;
		}return ans;
	}
	inline void init(int x){
		memset(vis,0,sizeof(vis));
		pw[1]=1;co=0;
		F(i,2,x){
			if(!vis[i])pw[i]=ksm(i,m,x),prime[++co]=i;
			F(j,1,co){
				if(prime[j]*i>=x)break;
				vis[prime[j]*i]=1;
				pw[prime[j]*i]=1ll*pw[i]*pw[prime[j]]%x;
				if(i%prime[j]==0)break;
			}
		}
	}
	const int md=998244353;
	inline short main(){
		file();
		read();
		int T=read();
		while(T--){
			c=read(),m=read();int ans=1;
			F(i,1,c){
				int p=read();
				init(p);int cnt=0;
				F(j,1,p)if(pw[j]%p==j%p)cnt++;
				ans=1ll*ans*cnt%md;
			}pi(ans);pn();
		}
		return 0;
	}
}
signed main(){return EMT::main();}

2021-09-22 19:49:53 星期三

Lesson5

拓扑求出一个点作为终点的最长路和作为起点的最长路,用堆维护即可。

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	const int inf=1e9;
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("johnny.in","r",stdin);freopen("johnny.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int N=1e5+10,M=1e6+10;
	struct que{
		std::priority_queue<int>a,b;
		inline void push(int x){a.push(x);}
		inline void pop(int x){b.push(x);}
		inline int top(){while(!b.empty()&&a.top()==b.top())a.pop(),b.pop();return a.empty()?inf:a.top();}
		inline void init(){while(!a.empty())a.pop();while(!b.empty())b.pop();}
	}q;
	struct queue{
		int qq[N],hd,tl;
		inline void push(int x){qq[++tl]=x;}
		inline void pop(){hd++;}
		inline int front(){return qq[hd];}
		inline bool empty(){return hd>tl;}
		inline void init(){hd=1,tl=0;}
	}Q;
	int co,head[N],Head[N];
	struct node{
		int next,to,w;
	}e[M];int n,m,in[N],a[N],tim,dt[N],ds[N],ans,w;
	inline void add(int next,int to,int *head){e[++co]=(node){head[next],to};head[next]=co;}
	inline short main(){
		file();
		int T=read();
		while(T--){	
			co=0;F(i,1,n)head[i]=Head[i]=ds[i]=dt[i]=in[i]=a[i]=tim=0;
			q.init();
			n=read(),m=read();w=n;
			F(i,1,m){
				int x=read(),y=read();
				add(x,y,head);add(y,x,Head);in[y]++;
			}Q.init();
			F(i,1,n)if(!in[i])Q.push(i);
			while(!Q.empty()){
				int x=Q.front();Q.pop();a[++tim]=x;
				for(register int i=head[x];i;i=e[i].next){
					in[e[i].to]--;if(!in[e[i].to])Q.push(e[i].to);
				}
			}
			F(i,1,n)for(register int o=head[a[i]];o;o=e[o].next)dt[e[o].to]=max(dt[e[o].to],dt[a[i]]+1);
			D(i,n,1)for(register int o=Head[a[i]];o;o=e[o].next)ds[e[o].to]=max(ds[e[o].to],ds[a[i]]+1);
			F(i,1,n)q.push(ds[i]);
			ans=q.top();
			F(j,1,n){
				int x=a[j];q.pop(ds[x]);
				for(register int i=Head[x];i;i=e[i].next)q.pop(dt[e[i].to]+ds[x]+1);
				if(q.top()<ans)ans=q.top(),w=x;
				else if(q.top()==ans&&x<w)w=x;
				q.push(dt[x]);
				for(register int i=head[x];i;i=e[i].next)q.push(ds[e[i].to]+dt[x]+1);
			}
			pi(w);pi(ans);pn();
		}
		return 0;
	}
}
signed main(){return EMT::main();}

舞动的夜晚

考虑进行网络流之后在残量网络中求强连通分量即可。

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("night.in","r",stdin);freopen("night.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int N=1e5+10,inf=1e9;
	int co=1,head[N],Hd[N],dis[N];
	struct node{int next,to,w,from;}e[N<<3];
	inline void add(int next,int to,int w){e[++co]=(node){head[next],to,w,next};head[next]=co;}
	int n,m,t,bel1[N],bel2[N],cnt,S,T,dfn[N],low[N],tim;
	struct queue{
		int hd,tl,q[N];
		inline void push(int x){q[++tl]=x;}
		inline void pop(){hd++;}
		inline int front(){return q[hd];}
		inline bool empty(){return hd>tl;}
		inline void init(){hd=1,tl=0;}
	}q;
	struct stack{
		int tp,s[N];
		inline int top(){return s[tp];}
		inline void pop(){tp--;}
		inline void push(int x){s[++tp]=x;}
	}s;
	int edge[N];
	inline bool bfs(){
		q.init();
		F(i,1,cnt)head[i]=Hd[i];
		F(i,1,cnt)dis[i]=inf;
		dis[S]=0;q.push(S);
		while(!q.empty()){
			int x=q.front();q.pop();
			for(register int i=head[x];i;i=e[i].next)if(e[i].w){
				if(dis[e[i].to]>dis[x]+1){
					dis[e[i].to]=dis[x]+1;
					q.push(e[i].to);
				}
			}if(x==T)return 1;
		}return 0;
	}
	inline int dfs(int x,int in){
		if(x==T)return in;
		int rest=in,go;
		for(register int i=head[x],j;i;head[x]=i=e[i].next)if(e[i].w){
			if(dis[e[i].to]==dis[x]+1){
				go=dfs(e[i].to,min(rest,e[i].w));
				if(go)e[i].w-=go,e[i^1].w+=go,rest-=go;
				else dis[e[i].to]=0;
			}if(!rest)break;
		}return in-rest;
	}
	bool vis[N];int part,bel[N];
	inline void tj(int k){
		dfn[k]=low[k]=++tim;s.push(k);vis[k]=1;
		for(register int i=head[k],j;i;i=e[i].next)if(e[i].w){
			j=e[i].to;
			if(!dfn[j]){
				tj(j);
				low[k]=min(low[k],low[j]);
			}else if(vis[j])low[k]=min(low[k],dfn[j]);
		}
		if(low[k]==dfn[k]){
			++part;
			while(s.top()!=k){
				int x=s.top();s.pop();
				bel[x]=part;vis[x]=0;
			}s.pop();vis[k]=0;bel[k]=part;
		}
	}
	std::vector<int>vec;
	inline short main(){
		file();
		n=read(),m=read(),t=read();
		S=++cnt,T=++cnt;
		F(i,1,n)bel1[i]=++cnt;
		F(i,1,m)bel2[i]=++cnt;
		F(i,1,n)add(S,bel1[i],1),add(bel1[i],S,0);
		F(i,1,m)add(bel2[i],T,1),add(T,bel2[i],0);
		F(i,1,t){
			int x=bel1[read()],y=bel2[read()];
			add(x,y,inf),add(y,x,0);
			edge[i]=co;
		}
		int ans=0;
		F(i,1,cnt)Hd[i]=head[i];
		while(bfs())ans+=dfs(S,inf);
		// pi(ans);
		F(i,1,cnt)if(!dfn[i])tj(i);
		F(i,1,t){
			if(e[edge[i]^1].w){
				int u=e[edge[i]].from,v=e[edge[i]].to;
				if(bel[u]!=bel[v])vec.push_back(i);
			}
		}
		pi(vec.size());pn();
		if(vec.size())F(i,0,vec.size()-1)pi(vec[i]);
		return 0;
	}
}
signed main(){return EMT::main();}

穿越广场

用AC自动机进行dp设\(f_{i,j,k,l}\)表示总长度为i,有j个R,到AC自动机的k点匹配情况为l的方案数。

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("square.in","r",stdin);freopen("square.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int N=120,mod=1e9+7;
	int n,m,ans,f[N<<1][N][N<<1][4];std::queue<int>q;
	struct abc{
		int tot,son[N<<1][2],fail[N<<1],end[N<<1];
		inline void insert(char *s,int id){
			int len=strlen(s),now=0;
			F(i,0,len-1){
				int x=(s[i]=='R');
				if(!son[now][x])son[now][x]=++tot;
				now=son[now][x];
			}end[now]|=id;
		}
		inline void getfail(){
			if(son[0][0])q.push(son[0][0]);
			if(son[0][1])q.push(son[0][1]);
			while(!q.empty()){
				int x=q.front();q.pop();
				if(son[x][1])fail[son[x][1]]=son[fail[x]][1],q.push(son[x][1]);
				else son[x][1]=son[fail[x]][1];
				if(son[x][0])fail[son[x][0]]=son[fail[x]][0],q.push(son[x][0]);
				else son[x][0]=son[fail[x]][0];
				end[son[x][1]]|=end[son[fail[x]][1]];
				end[son[x][0]]|=end[son[fail[x]][0]];
			}
		}
		inline void getans(){
			f[0][0][0][0]=1;
			F(i,0,n+m)
			F(j,0,i){
				if(j>m||i-j>n)continue;
				F(k,0,tot)
				F(l,0,3)
				(f[i+1][j+1][son[k][1]][l|end[son[k][1]]]+=f[i][j][k][l])%=mod,
				(f[i+1][j][son[k][0]][l|end[son[k][0]]]+=f[i][j][k][l])%=mod;
			}
			ans=0;
			F(i,0,tot)ans+=f[n+m][m][i][3],ans-=ans>=mod?mod:0;
			pi(ans);pn();
		}
		inline void init(){
			memset(f,0,sizeof(f));
			memset(son,0,sizeof(son));
			memset(fail,0,sizeof(fail));
			memset(end,0,sizeof(end));
			tot=0;
		}
	}AC;
	char s[N];
	inline short main(){
		file();
		int T=read();
		while(T--){
			AC.init();
			m=read(),n=read();
			scanf("%s",s);AC.insert(s,1);
			scanf("%s",s);AC.insert(s,2);
			AC.getfail();
			AC.getans();
		}
		return 0;
	}
}
signed main(){return EMT::main();}

贝尔数

注意到模数=\(31\times 37\times 41\times 43\times 47\),预处理出这几个模数以内的贝尔数再用矩阵快速幂优化递推再用CRT合并即可。

Code


#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace lit{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("bell.in","r",stdin);freopen("bell.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int N=3e3+10,mod=95041567;
	int bell[N]={1,1,2,5,15,52,203},C[N][N];
	inline int ksm(int a,int b){
		int ans=1;
		while(b){
			if(b&1)ans=1ll*a*ans%mod;
			b>>=1;a=1ll*a*a%mod;
		}return ans;
	}
	inline short main(){
		C[0][0]=C[1][0]=C[1][1]=1;
		F(i,2,2300){
			C[i][0]=C[i][i]=1;
			F(j,1,i-1)C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;
		}
		F(n,6,2300)
			F(k,0,n)bell[n+1]+=1ll*C[n][k]*bell[k]%mod,bell[n+1]-=bell[n+1]>=mod?mod:0;
		return 0;
	}
}
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("bell.in","r",stdin);freopen("bell.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	struct S1{
		const int mod=31;
		int C[100][100];
		int bell[100]={1,1,2,5,15,52,203};
		inline void init(){
			C[0][0]=C[1][1]=C[1][0]=1;
			F(i,2,mod*2){
				C[i][0]=C[i][i]=1;
				F(j,1,i-1)C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
			}
			F(n,6,mod*2)
				F(k,0,n)
					bell[n+1]+=1ll*C[n][k]*bell[k]%mod,bell[n+1]-=bell[n+1]>=mod?mod:0;
		}
		int b[55][55],c[55][55],f[55],w[55];
		inline void muls(int a[55][55]){
			memset(c,0,sizeof(c));
			F(i,1,mod)F(j,1,mod)F(k,1,mod)(c[i][j]+=1ll*a[i][k]*a[k][j]%mod)%=mod;
			F(i,1,mod)F(j,1,mod)a[i][j]=c[i][j];
		}
		inline void mul(int a[55],int b[55][55]){
			memset(w,0,sizeof(w));
			F(i,1,mod)F(j,1,mod)(w[i]+=1ll*a[j]*b[j][i]%mod)%=mod;
			F(i,1,mod)a[i]=w[i];
		}
		inline int reset(int n){
			memset(b,0,sizeof(b));
			b[1][1]=1;
			F(i,2,mod)b[i-1][i]=b[i][i]=1;
			b[mod][1]=1;b[mod][2]=1;
			int ceng=n-(mod-1)*mod;ceng/=mod;
			F(i,1,mod)f[i]=C[mod-1][i-1];
			while(ceng){
				if(ceng&1)mul(f,b);
				muls(b);
				ceng>>=1;
			}int begin=n%mod;
			int ans=0;
			F(i,1,mod)(ans+=1ll*bell[begin+i-1]*f[i]%mod)%=mod;
			return ans;
		}
	}s1;
	struct S2{
		const int mod=37;
		int C[100][100];
		int bell[100]={1,1,2,5,15,52,203};
		inline void init(){
			C[0][0]=C[1][1]=C[1][0]=1;
			F(i,2,mod*2){
				C[i][0]=C[i][i]=1;
				F(j,1,i-1)C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
			}
			F(n,6,mod*2)
				F(k,0,n)
					bell[n+1]+=1ll*C[n][k]*bell[k]%mod,bell[n+1]-=bell[n+1]>=mod?mod:0;
		}
		int b[55][55],c[55][55],f[55],w[55];
		inline void muls(int a[55][55]){
			memset(c,0,sizeof(c));
			F(i,1,mod)F(j,1,mod)F(k,1,mod)(c[i][j]+=1ll*a[i][k]*a[k][j]%mod)%=mod;
			F(i,1,mod)F(j,1,mod)a[i][j]=c[i][j];
		}
		inline void mul(int a[55],int b[55][55]){
			memset(w,0,sizeof(w));
			F(i,1,mod)F(j,1,mod)(w[i]+=1ll*a[j]*b[j][i]%mod)%=mod;
			F(i,1,mod)a[i]=w[i];
		}
		inline int reset(int n){
			memset(b,0,sizeof(b));
			b[1][1]=1;
			F(i,2,mod)b[i-1][i]=b[i][i]=1;
			b[mod][1]=1;b[mod][2]=1;
			int ceng=n-(mod-1)*mod;
			F(i,1,mod)f[i]=C[mod-1][i-1];ceng/=mod;
			while(ceng){
				if(ceng&1)mul(f,b);
				muls(b);
				ceng>>=1;
			}int begin=n%mod;
			int ans=0;
			F(i,1,mod)(ans+=1ll*bell[begin+i-1]*f[i]%mod)%=mod;
			return ans;
		}
	}s2;
	struct S3{
		const int mod=41;
		int C[100][100];
		int bell[100]={1,1,2,5,15,52,203};
		inline void init(){
			C[0][0]=C[1][1]=C[1][0]=1;
			F(i,2,mod*2){
				C[i][0]=C[i][i]=1;
				F(j,1,i-1)C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
			}
			F(n,6,mod*2)
				F(k,0,n)
					bell[n+1]+=1ll*C[n][k]*bell[k]%mod,bell[n+1]-=bell[n+1]>=mod?mod:0;
		}
		int b[55][55],c[55][55],f[55],w[55];
		inline void muls(int a[55][55]){
			memset(c,0,sizeof(c));
			F(i,1,mod)F(j,1,mod)F(k,1,mod)(c[i][j]+=1ll*a[i][k]*a[k][j]%mod)%=mod;
			F(i,1,mod)F(j,1,mod)a[i][j]=c[i][j];
		}
		inline void mul(int a[55],int b[55][55]){
			memset(w,0,sizeof(w));
			F(i,1,mod)F(j,1,mod)(w[i]+=1ll*a[j]*b[j][i]%mod)%=mod;
			F(i,1,mod)a[i]=w[i];
		}
		inline int reset(int n){
			memset(b,0,sizeof(b));
			b[1][1]=1;
			F(i,2,mod)b[i-1][i]=b[i][i]=1;
			b[mod][1]=1;b[mod][2]=1;
			int ceng=n-(mod-1)*mod;ceng/=mod;
			F(i,1,mod)f[i]=C[mod-1][i-1];
			while(ceng){
				if(ceng&1)mul(f,b);
				muls(b);
				ceng>>=1;
			}int begin=n%mod;
			int ans=0;
			F(i,1,mod)(ans+=1ll*bell[begin+i-1]*f[i]%mod)%=mod;
			return ans;
		}
	}s3;
	struct S4{
		const int mod=43;
		int C[100][100];
		int bell[100]={1,1,2,5,15,52,203};
		inline void init(){
			C[0][0]=C[1][1]=C[1][0]=1;
			F(i,2,mod*2){
				C[i][0]=C[i][i]=1;
				F(j,1,i-1)C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
			}
			F(n,6,mod*2)
				F(k,0,n)
					bell[n+1]+=1ll*C[n][k]*bell[k]%mod,bell[n+1]-=bell[n+1]>=mod?mod:0;
		}
		int b[55][55],c[55][55],f[55],w[55];
		inline void muls(int a[55][55]){
			memset(c,0,sizeof(c));
			F(i,1,mod)F(j,1,mod)F(k,1,mod)(c[i][j]+=1ll*a[i][k]*a[k][j]%mod)%=mod;
			F(i,1,mod)F(j,1,mod)a[i][j]=c[i][j];
		}
		inline void mul(int a[55],int b[55][55]){
			memset(w,0,sizeof(w));
			F(i,1,mod)F(j,1,mod)(w[i]+=1ll*a[j]*b[j][i]%mod)%=mod;
			F(i,1,mod)a[i]=w[i];
		}
		inline int reset(int n){
			memset(b,0,sizeof(b));
			b[1][1]=1;
			F(i,2,mod)b[i-1][i]=b[i][i]=1;
			b[mod][1]=1;b[mod][2]=1;
			int ceng=n-(mod-1)*mod;ceng/=mod;
			F(i,1,mod)f[i]=C[mod-1][i-1];
			while(ceng){
				if(ceng&1)mul(f,b);
				muls(b);
				ceng>>=1;
			}int begin=n%mod;
			int ans=0;
			F(i,1,mod)(ans+=1ll*bell[begin+i-1]*f[i]%mod)%=mod;
			return ans;
		}
	}s4;
	struct S5{
		const int mod=47;
		int C[110][100];
		int bell[100]={1,1,2,5,15,52,203};
		inline void init(){
			C[0][0]=C[1][1]=C[1][0]=1;
			F(i,2,mod*2){
				C[i][0]=C[i][i]=1;
				F(j,1,i-1)C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
			}
			F(n,6,mod*2){
				F(k,0,n)
					bell[n+1]+=1ll*C[n][k]*bell[k]%mod,bell[n+1]-=bell[n+1]>=mod?mod:0;
			}
		}
		int b[55][55],c[55][55],f[55],w[55];
		inline void muls(int a[55][55]){
			memset(c,0,sizeof(c));
			F(i,1,mod)F(j,1,mod)F(k,1,mod)(c[i][j]+=1ll*a[i][k]*a[k][j]%mod)%=mod;
			F(i,1,mod)F(j,1,mod)a[i][j]=c[i][j];
		}
		inline void mul(int a[55],int b[55][55]){
			memset(w,0,sizeof(w));
			F(i,1,mod)F(j,1,mod)(w[i]+=1ll*a[j]*b[j][i]%mod)%=mod;
			F(i,1,mod)a[i]=w[i];
		}
		inline int reset(int n){
			memset(b,0,sizeof(b));
			b[1][1]=1;
			F(i,2,mod)b[i-1][i]=b[i][i]=1;
			b[mod][1]=1;b[mod][2]=1;
			int ceng=n-(mod-1)*mod;ceng/=mod;
			F(i,1,mod)f[i]=C[mod-1][i-1];
			while(ceng){
				if(ceng&1)mul(f,b);
				muls(b);
				ceng>>=1;
			}int begin=n%mod;
			int ans=0;
			F(i,1,mod)(ans+=1ll*bell[begin+i-1]*f[i]%mod)%=mod;
			return ans;
		}
	}s5;
	inline void exgcd(int a,int b,int &x,int &y){
		if(!b){x=1;y=0;return;}
		exgcd(b,a%b,x,y);
		int z=x;x=y;y=z-y*(a/b);
	}
	int c[10],a[10]={0,31,37,41,43,47},b[10],tot=95041567;ll ans;
	inline int CRT(){
		ans=0;
		F(i,1,5){
			c[i]=tot/a[i];
			int x=0,y=0;exgcd(c[i],a[i],x,y);
			ans+=1ll*c[i]*b[i]*(x<0?x+a[i]:x)%95041567,ans-=ans>=95041567?95041567:0;
		}return ans%95041567;
	}
	inline short main(){
		file();
		s1.init();s2.init();s3.init();s4.init();s5.init();
		int T=read();
		lit::main();
		while(T--){
			int n=read();
			if(n<=2300){pi(lit::bell[n]),pn();continue;}
			b[1]=s1.reset(n),b[2]=s2.reset(n),b[3]=s3.reset(n),b[4]=s4.reset(n),b[5]=s5.reset(n);
			pi(CRT());pn();
		}
		return 0;
	}
}
signed main(){return EMT::main();}

擒敌拳

由于不会李超树,考虑测试点分治。

Code


#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("b.in","r",stdin);freopen("b.out","w",stdout);}
	inline ll max(ll a,ll b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(ll x){pf("%lld ",x);}inline void pn(){pf("\n");}
	int rt[3100];
	struct zxs{
		int val[3100*20],ls[3100*20],rs[3100*20],tot;
		inline void insert(int x,int &y,int l,int r,int v){
			y=++tot;ls[y]=ls[x],rs[y]=rs[x];
			val[y]=val[x]+1;
			if(l==r)return;
			int mid=(l+r)>>1;
			if(v<=mid)insert(ls[x],ls[y],l,mid,v);
			else insert(rs[x],rs[y],mid+1,r,v);
		}
		inline int ask(int x,int y,int l,int r,int ql,int qr){
			if(l>=ql&&r<=qr)return val[y]-val[x];
			int mid=(l+r)>>1;
			if(qr<=mid)return ask(ls[x],ls[y],l,mid,ql,qr);
			else if(ql>mid)return ask(rs[x],rs[y],mid+1,r,ql,qr);
			else return ask(ls[x],ls[y],l,mid,ql,mid)+ask(rs[x],rs[y],mid+1,r,mid+1,qr);
		}
	}segm;
	const int N=2e5+10;
	int stack[N],tp;
	ll dp[N];
	int n,a[N],s[N],lmax[N],rmax[N],hd,tl,spj=1;
	inline void solve(){
		F(i,1,n){
			dp[i]=dp[i-1];
			bool fl=0;
			while(tp&&a[stack[tp]]>=a[i])tp--,fl=1;
			if(!fl)stack[++tp]=i;
			else a[stack[++tp]]=a[i];
			D(j,tp,1)
				dp[i]=max(dp[i],1ll*a[stack[j]]*(i-stack[j]+1));
			pi(dp[i]);
		}
	}
	struct dp{int plc,val;}q[N];
	inline db lop(int k,int j){return (db)(1.0*a[k]*k-1.0*a[j]*j+a[j]-a[k])/(db)(a[k]-a[j]);}
	inline short main(){
		file();
		n=read();
		F(i,1,n)s[i]=a[i]=read(),spj&=(a[i]>=a[i-1]);
		if(n<=3000){
			std::sort(s+1,s+n+1);
			int len=std::unique(s+1,s+n+1)-s-1;
			F(i,1,n)a[i]=std::lower_bound(s+1,s+len+1,a[i])-s;
			F(i,1,n){
				segm.insert(rt[i-1],rt[i],1,len,a[i]);
				int l=1,r=i,an;
				while(l<=r){
					int mid=(l+r)>>1;
					if(segm.ask(rt[mid-1],rt[i],1,len,a[i],len)==(i-mid+1))r=mid-1,an=mid;
					else l=mid+1;
				}lmax[i]=an;
				ll ans=0;
				F(j,1,i){
					if(rmax[j]){ans=max(ans,1ll*(rmax[j]-lmax[j]+1)*s[a[j]]);continue;}
					l=j,r=i;
					while(l<=r){
						int mid=(l+r)>>1;
						if(segm.ask(rt[j-1],rt[mid],1,len,a[j],len)==(mid-j+1))l=mid+1,an=mid;
						else r=mid-1;
					}if(an!=i)rmax[j]=an;
					ans=max(ans,(r-lmax[j]+1)*s[a[j]]);
				}pi(ans);
			}return 0;
		}
		if(spj){
			F(i,1,n){
				dp[i]=dp[i-1];
				while(tl>1&&lop(stack[tl],stack[tl-1])>lop(i,stack[tl]))tl--;
				stack[++tl]=i;
				int now=tl;
				while(now>1&&lop(stack[now],stack[now-1])>=i){
					dp[i]=max(dp[i],1ll*a[stack[now]]*(i-stack[now]+1));now--;
				}dp[i]=max(dp[i],1ll*a[stack[now]]*(i-stack[now]+1));
				pi(dp[i]);
			}
		}else solve();
		return 0;
	}
}
signed main(){return EMT::main();}

柱状图

对每个点三分出最优的答案,用树状数组记录权值和与个数维护即可。

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("c.in","r",stdin);freopen("c.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline ll min(ll a,ll b){return a<b?a:b;}
	inline void pi(ll x){pf("%lld ",x);}inline void pn(){pf("\n");}
	const int N=1e5+10;
	ll trv[N<<1],tlv[N<<1];int trc[N<<1],tlc[N<<1];
	int len,s[N<<1],v1[N],v2[N],n;
	inline void add(ll *t,int x,int v){while(x<=len)t[x]+=v,x+=x&-x;}
	inline void add(int *t,int x,int v){while(x<=len)t[x]+=v,x+=x&-x;}
	inline ll ask(ll *t,int x){ll ans=0;while(x)ans+=t[x],x-=x&-x;return ans;}
	inline int ask(int *t,int x){int ans=0;while(x)ans+=t[x],x-=x&-x;return ans;}
	inline ll check(int x,int val){
		if(val-(x-1)<=0||val-(n-x)<=0)return 1e18;
		int val1=val+x,val2=val-x;
		val1=std::upper_bound(s+1,s+len+1,val1)-s-1;
		val2=std::upper_bound(s+1,s+len+1,val2)-s-1;
		int c1,c2;ll vv1,vv2;
		c1=ask(trc,val1),c2=ask(trc,len)-c1;
		vv1=ask(trv,val1),vv2=ask(trv,len)-vv1;
		ll ans=0;
		ans=1ll*c1*(val+x)-vv1+vv2-1ll*c2*(val+x);
		c1=ask(tlc,val2),c2=ask(tlc,len)-c1;
		vv1=ask(tlv,val2),vv2=ask(tlv,len)-vv1;
		ans+=1ll*c1*(val-x)-vv1+vv2-1ll*c2*(val-x);
		return ans;
	}
	inline short main(){
		file();
		n=read();
		F(i,1,n){
			int x=read();v1[i]=x+i,v2[i]=x-i;
			s[++len]=v1[i],s[++len]=v2[i];
		}
		std::sort(s+1,s+len+1);
		len=std::unique(s+1,s+len+1)-s-1;
		F(i,1,n)v1[i]=std::lower_bound(s+1,s+len+1,v1[i])-s,v2[i]=std::lower_bound(s+1,s+len+1,v2[i])-s;
		F(i,1,n)add(trv,v1[i],s[v1[i]]),add(trc,v1[i],1);
		ll ans=1e18;
		F(i,1,n){
			int l=1,r=1e9;
			while(r-l>=3){
				int mid1=l+(r-l)/3,mid2=r-(r-l)/3;
				if(check(i,mid1)<check(i,mid2))r=mid2;
				else l=mid1;
			}F(j,l,r)ans=min(ans,check(i,j));
			add(trv,v1[i],-s[v1[i]]),add(trc,v1[i],-1);
			add(tlv,v2[i],s[v2[i]]),add(tlc,v2[i],1);
		}pi(ans);
		return 0;
	}
}
signed main(){return EMT::main();}

2021-09-20 17:18:18 星期一 ## D 从小往大枚举k,暴力求解,好像卡不掉?
Code


#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("kdgraph.in","r",stdin);freopen("kdgraph.out","w",stdout);}
	inline ll max(ll a,ll b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int N=1e6+10;
	struct jws{ll n,m,b;}js;
	struct jsw{ll point,edge,in;}ans;
	bool vis[N],ban[N];
	int n,m,co,head[N],deg[N],An;ll an=-1e18;
	std::queue<int>q;
	struct node{int next,to;}e[N<<1];
	inline void add(int next,int to){e[++co]=(node){head[next],to},head[next]=co;}
	inline void dfs(int k,int from){
		vis[k]=1;ans.point++;
		for(register int i=head[k],j;i;i=e[i].next){
			j=e[i].to;
			if(ban[j])ans.edge++;
			else{ans.in++;if(!vis[j])dfs(j,k);}
		}
	}
	inline short main(){
		file();
		n=read(),m=read();
		js.m=read(),js.n=read(),js.b=read();
		F(i,1,m){
			int x=read(),y=read();
			deg[x]++;deg[y]++;
			add(x,y);add(y,x);
		}
		F(i,1,n)if(!deg[i])ban[i]=1;
		F(k,1,n){
			bool fl=1;
			F(i,1,n)if(deg[i]>=k)vis[i]=0,fl=0;
			if(fl)break;
			F(i,1,n)if(!vis[i]&&!ban[i]){
				ans.point=ans.in=ans.edge=0;
				dfs(i,0);ans.in/=2;
				if(an<-ans.point*js.n+ans.edge*js.b+ans.in*js.m){
					an=-ans.point*js.n+ans.edge*js.b+ans.in*js.m;
					An=k;
				}else if(an==-ans.point*js.n+ans.edge*js.b+ans.in*js.m)An=k;
			}
			F(i,1,n)if(deg[i]==k)q.push(i);
			while(!q.empty()){
				int x=q.front();q.pop();ban[x]=1;
				for(register int i=head[x],j;i;i=e[i].next){
					j=e[i].to;if(ban[j])continue;
					deg[j]--;
					if(deg[j]==k)q.push(j);
				}
			}
		}pf("%d %lld",An,an);
		return 0;
	}
}
signed main(){return EMT::main();}

C

用bitset n^3水过了,建议加强数据

Code


#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<bitset>
#include<unordered_map>
#include<algorithm>
#include<vector>
using std::cin;
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("class.in","r",stdin);freopen("class.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int N=1100;std::bitset<N>fa[N];
	std::unordered_map<std::string,int>mp;
	int co,n,dp[N],cnt,v[N];std::string s,base;
	inline void no(){pf("greska\n");}
	inline void yes(){pf("ok\n");}
	inline short main(){
		file();
		cin>>n;
		while(n--){
			cnt=0;
			cin>>s;base=s;bool fl=1;
			if(mp[s]){no();while(s[0]!=';')cin>>s;continue;}
			while(s[0]!=':')cin>>s;
			cin>>s;
			while(s[0]!=';'){
				int x=mp[s];if(!x){fl=0;while(s[0]!=';')cin>>s;break;}
				v[++cnt]=x;cin>>s;
			}
			F(i,1,cnt){F(j,i+1,cnt)if((fa[v[i]]&fa[v[j]]).count())
			{if(!fa[v[i]][v[j]]&&!fa[v[j]][v[i]]){fl=0;break;}}if(!fl)break;}
			if(fl){
				yes();mp[base]=++co;fa[co][co]=1;
				F(i,1,cnt)fa[co]|=fa[v[i]];
			}else no();
		}
		return 0;
	}
}
signed main(){return EMT::main();}

B

开两个变量记录现在A和P的数量即可O(n)求解

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<queue>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("apstr.in","r",stdin);freopen("apstr.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	char s[10005];
	int n,suma,sumb,ans;
	inline short main(){
		file();
		scanf("%s",s+1);
		n=strlen(s+1);
		F(i,1,n)if(s[i]=='A')suma++;else{
			if(suma)suma--,ans++;
			else sumb++;
		}sumb%=2;
		pi(sumb+suma);
		return 0;
	}
}
signed main(){return EMT::main();}

A

暴力模拟即可。

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("ip.in","r",stdin);freopen("ip.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d",x);}inline void pn(){pf("\n");}
	char s[35],S[35];int ans[5],slen;
	inline short main(){
		file();
		scanf("%s",s+1);int len=strlen(s+1);s[len+1]='.';
		int key=0;
		F(i,1,4){
			int x=0;bool fl=1;key++;char ch=s[key];
			while(ch<'0'||ch>'9')key++,ch=s[key];
			while(ch>='0'&&ch<='9'){
				if(fl)x=x*10+ch-'0';key++;ch=s[key];
				if(x>255)fl=0,ans[i]=255;
			}if(!ans[i])ans[i]=x;
		}
		F(i,1,4){
			if(ans[i]>=100){
				int a100=ans[i]/100,a10=ans[i]/10-a100*10,a1=ans[i]-a10*10-a100*100;
				S[++slen]=a100+'0',S[++slen]=a10+'0',S[++slen]=a1+'0';
			}
			else if(ans[i]>=10){
				int a10=ans[i]/10,a1=ans[i]-a10*10;
				S[++slen]=a10+'0',S[++slen]=a1+'0';
			}else S[++slen]=ans[i]+'0';
			if(i!=4)S[++slen]='.';
		}bool fl=1;
		if(len!=slen)fl=0;
		F(i,1,len)if(s[i]!=S[i])fl=0;
		puts(fl?"YES":"NO");
		if(fl)return 0;
		pf("%s",S+1);
		return 0;
	}
}
signed main(){return EMT::main();}

2021-09-19 19:22:25 星期日

种田

考试时在1e9内暴力rand,稳定70pts,加上没脸qj数据点套得\(s/t\),可不用数据点分治直接求出答案。

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<ctime>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define int long long
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("d.in","r",stdin);freopen("d.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	int n,ans=1e9;const int N=3e5+10;
	inline int random(int x){return rand()*rand()%x;}
	struct thing{int a,b,c,val;
	friend bool operator <(thing a,thing b){return a.val<b.val;}}p[N<<1];
	inline void check(int s,int t){
		F(i,1,n)p[i].val=p[i].a*(db)s/(db)t+p[i].b;
		std::sort(p+1,p+n+1);
		int lv=p[1].val,lk=1,rv=p[n].val,rk=n,l=1,r=n;
		while(!p[l].c){
			l++;
			if(p[l].val!=lv)lv=p[l].val,lk=l;
		}l=lk;
		while(!p[r].c){
			r--;
			if(p[r].val!=rv)rv=p[r].val,rk=r;
		}r=rk;
		ans=min(ans,r-l+1);
	}
	void begin();
	inline short main(){
		file();
		srand(time(0));
		n=read();
		F(i,1,n)p[i].a=read(),p[i].b=read(),p[i].c=read();
		begin();
		while(1){
			if(clock()>=950000)break;
			int s=(random(2)&1?1:-1)*random(100000000);
			int t=(random(2)&1?1:-1)*random(100000000);
			check(s,t);
		}pi(n<=2000?ans:ans-1);
		return 0;
	}
	void begin(){
		check(1,0);check(0,1);
		check(1,1);check(1,2);check(1,-1);check(1,-2);
		check(5226,1);check(-1324,1);check(67,1);check(15000,1);
		check(5,10);check(-965,100);check(-18896,1);
	}
}
signed main(){return EMT::main();}

高考

首先得到每种结果的概率都相等,通过一种方案的概率乘上方案总数可以算到每种情况的概率相等

\[\frac{\prod\limits_{i=1}^{n}(a_i-1)!}{n(n+1)...(n+m-1)}\times \frac{m!}{\prod\limits_{i=1}^{n}(a_i-1)!}=\frac{1}{C_{n+m-1}^{n-1}} \]

考虑到贡献乘概率,设\(f_{i,j}\)表示至少i个数>=j的方案数,则对于一个r的答案为

\[\sum\limits_{k=1}^{r}\sum\limits_{l=1}^{m}f(k,l) \]

因为每个数的贡献在这个式子中会通过重复部分巧妙地累加上去。
\(g_{i,j}\)表示恰好i个数>=j的方案数,则f是g的后缀和。
g可通过二项式反演容斥得到,设\(h(i,j)\)表示至少i个数>=j的方案数,注意h和f定义不一样,h还考虑到到达结果的路径,而f只考虑结果。
考虑钦定i个数>=j,将剩下的m+n-jk分到n个数上,于是

\[h_{i,j}=C_{n}^{i}\times C_{n+m-1-ij}^{n-1} \]

\[g_{i,j}=\sum\limits_{k=i}^{n}C_{k}^{i}(-1)^{k-i}h_{k,j} \]

于是就可做了.

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("c.in","r",stdin);freopen("c.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int N=5e3+10,M=100000,mod=1e9+7;
	int jc[M],inv[M],n,m,g[N][N],f[N][N];
	inline int ksm(int a,int b){
		int ans=1;
		while(b){
			if(b&1)ans=1ll*ans*a%mod;
			b>>=1;a=1ll*a*a%mod;
		}return ans;
	}
	inline int C(int n,int m){if(m<0||m>n)return 0;return 1ll*jc[n]*inv[m]%mod*inv[n-m]%mod;}
	inline short main(){
		file();
		n=read(),m=read();
		jc[0]=1;inv[0]=inv[1]=1;
		F(i,1,n+m)jc[i]=1ll*jc[i-1]*i%mod;
		inv[n+m]=ksm(jc[n+m],mod-2);
		D(i,n+m,3)inv[i-1]=1ll*inv[i]*i%mod;
		F(i,1,n)F(j,1,m/i)F(k,i,min(m/j,n))
		g[i][j]+=1ll*C(k,i)%mod*((k-i)&1?-1:1)*C(n,k)%mod*C(m+n-1-j*k,n-1)%mod,
		g[i][j]-=g[i][j]>=mod?mod:(g[i][j]<0?-mod:0);
		D(i,n,1)D(j,m/i,1)f[i][j]=f[i+1][j]+g[i][j],f[i][j]-=f[i][j]>=mod?mod:0;
		int sum=0,Inv=ksm(C(n+m-1,n-1),mod-2);
		F(r,1,n){
			F(l,1,m)sum+=f[r][l],sum-=sum>=mod?mod:0;
			pi(1ll*(1ll*sum*Inv%mod+r)%mod);pn();
		}
		return 0;
	}
}
signed main(){return EMT::main();}

底垫

用珂朵莉树维护1-1e9上每个数现在被哪个点代表的区间所覆盖,将问题离线按r从小到大排序,当目前指针指到i时,若i原来覆盖的区间中长度为k的子区间被t所覆盖,那么对于左端点为[t+1,i]的问题有\((i − l +1)(r − i + 1)k\)的贡献(因为原来碰不到现在能碰到了),相反对于[1,t]的问题就碰不到了,于是减去\((i − t)(r − i + 1)k\)的贡献,用树状数组分l,r,lr,c的系数维护即可。

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<set>
using std::set;
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("b.in","r",stdin);freopen("b.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int N=2e5+10,mod=1e9+7;
	int n,m,l[N],r[N];
	struct tzsz{
		int val[N];
		inline void add(int x,int v){while(x)val[x]+=v,val[x]-=val[x]>=mod?mod:0,x-=x&-x;}
		inline int ask(int x){int ans=0;while(x<=n)ans+=val[x],ans-=ans>=mod?mod:0,x+=x&-x;return ans;}
	}tl,tr,tlr,tc;
	struct node{
		int l,r;mutable int last;
		node(int l,int r=0,int last=0):l(l),r(r),last(last){}
		friend bool operator <(node a,node b){return a.l<b.l;}
	};
	struct qus{
		int l,r,id;
		friend bool operator<(qus a,qus b){return a.r<b.r;}
	}q[N];
	set<node>s;
	typedef set<node>::iterator sit;
	inline sit split(int pos){
		sit it=s.lower_bound(node(pos));
		if(it!=s.end()&&it->l==pos)return it;
		it--;if(it->r<pos)return s.end();
		int l=it->l,r=it->r,v=it->last;
		s.erase(it);
		s.insert(node(l,pos-1,v));
		return s.insert(node(pos,r,v)).first;
	}
	inline void assign(int l,int r,int tim){
		sit itr=split(r+1),now=split(l);sit itl=now;
		while(now!=itr){
			int len=now->r-now->l+1,lasttim=now->last;
			tl.add(tim,1ll*(-1+tim)*len%mod);tl.add(lasttim,1ll*(1-tim+mod)*len%mod);
			tr.add(tim,1ll*(tim+1)*len%mod);tr.add(lasttim,1ll*(-lasttim-1+mod)*len%mod);
			tlr.add(tim,1ll*(-1+mod)*len%mod);tlr.add(lasttim,len);
			tc.add(tim,1ll*(1-1ll*tim*tim%mod+mod)%mod*len%mod);
			tc.add(lasttim,1ll*(((tim-lasttim)%mod+1ll*tim*lasttim%mod)%mod-1+mod)%mod*len%mod);
			now++;
		}s.erase(itl,itr);
		s.insert(node(l,r,tim));
	}
	inline int ksm(int a,int b){
		int ans=1;
		while(b){
			if(b&1)ans=1ll*a*ans%mod;
			b>>=1;a=1ll*a*a%mod;
		}return ans;
	}
	int Ans[N];
	inline short main(){
		file();
		n=read(),m=read();
		F(i,1,n)l[i]=read(),r[i]=read()-1;
		F(i,1,m)q[i].l=read(),q[i].r=read(),q[i].id=i;
		std::sort(q+1,q+m+1);
		int key=0;
		s.insert(node(1,1e9,0));
		F(i,1,m){
			while(key<q[i].r)key++,assign(l[key],r[key],key);
			int len=q[i].r-q[i].l+1,inv=ksm(1ll*len*(len+1)/2%mod,mod-2);
			int ans=1ll*tl.ask(q[i].l)*q[i].l%mod;
			ans+=1ll*tr.ask(q[i].l)*q[i].r%mod,ans-=ans>=mod?mod:0;
			ans+=1ll*tlr.ask(q[i].l)*q[i].l%mod*q[i].r%mod,ans-=ans>=mod?mod:0;
			ans+=tc.ask(q[i].l),ans-=ans>=mod?mod:0;
			ans=1ll*ans*inv%mod;
			Ans[q[i].id]=ans;
		}
		F(i,1,m)pi(Ans[i]),pn();
		return 0;
	}
}
signed main(){return EMT::main();}

爆零

是道同学们都做过的原题(除了我)
但是当时场切就很多,我这场没做出来还是自己的原因。
\(f_i\)表示处理完i的子树最少多少步,记录\(mxdep_i\)表示i子树中最深的点,当\(mxdep_i<deep_i*2\)时说明从这里走到别处比从1走更优,于是可以补一下差价,答案就是\(f_1\)

Code
#include<bits/stdc++.h>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("a.in","r",stdin);freopen("a.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int N=1e6+10;
	int deep[N],mxdep[N],n,head[N],co,f[N];
	struct node{int next,to;}e[N];
	std::vector<int>son[N];
	inline bool com(int i,int j){return mxdep[i]<mxdep[j];}
	inline void add(int next,int to){e[++co]=(node){head[next],to};head[next]=co;}
	inline void dfs(int k){
		mxdep[k]=deep[k];
		for(register int i=head[k],j;i;i=e[i].next){
			j=e[i].to;deep[j]=deep[k]+1;
			son[k].push_back(j);
			dfs(j);mxdep[k]=max(mxdep[k],mxdep[j]);
		}std::sort(son[k].begin(),son[k].end(),com);
	}
	inline void Dfs(int k){
		if(son[k].size()){Dfs(son[k][son[k].size()-1]),f[k]+=f[son[k][son[k].size()-1]];}
		else {f[k]=deep[k];return;}
		F(i,0,(int)son[k].size()-2){
			int j=son[k][i];
			Dfs(j);f[k]+=f[j];
			if(mxdep[j]<=deep[k]*2)f[k]-=deep[k]*2,f[k]+=mxdep[j];
		}
	}
	inline short main(){
		file();
		n=read();F(i,2,n)add(read(),i);
		dfs(1);Dfs(1);pi(f[1]);
		return 0;
	}
}
signed main(){return EMT::main();}

2021-09-17 20:31:28 星期五

Permutation

题解

Code


#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("perm.in","r",stdin);freopen("perm.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int N=1e6+10,mod=1e9+7;
	int n,k,m,ans,jc[N],inv[N];
	inline int C(int n,int m){
		if(m>n||m<0||n<0)return 0;
		return 1ll*jc[n]*inv[m]%mod*inv[n-m]%mod;
	}
	inline int ksm(int a,int b){
		int ans=1;
		while(b){
			if(b&1)ans=1ll*a*ans%mod;
			a=1ll*a*a%mod;
			b>>=1;
		}return ans;
	}
	inline short main(){
		file();
		n=read(),k=read(),m=read();jc[0]=1;
		n=n-(k-m),k=m;
		F(i,1,n)jc[i]=1ll*jc[i-1]*i%mod;
		inv[n]=ksm(jc[n],mod-2);inv[0]=inv[1]=1;
		D(i,n-1,2)inv[i]=1ll*inv[i+1]*(i+1)%mod;
		if(k==1){pi(n-1);return 0;}
		F(i,2,k)ans+=C(n-i,k-i+2),ans-=ans>=mod?mod:0;
		F(i,2,n){
			int num=C(n-i-1,k-2);
			int tmp=i-1;
			ans+=1ll*num*tmp%mod,ans-=ans>=mod?mod:0;
		}pi(ans);
		return 0;
	}
}
signed main(){return EMT::main();}

小P的生成树

考虑将每个向量之间夹的角形成的范围分割开,每个范围内取一个向量求相对大小再用克鲁斯卡尔求解。

Code
#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("mst.in","r",stdin);freopen("mst.out","w",stdout);}
	inline db max(db a,db b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(db x){pf("%.6lf ",x);}inline void pn(){pf("\n");}
	const int N=55;
	const db pai=3.1415926535;
	int fa[N],co,head[N],n,m,cou;db ans,jiao[N*N*N*N];
	inline int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
	struct node{int u,v,a,b;db val;friend bool operator <(node a,node b){return a.val>b.val;}}e[N*N];
	inline void add(int next,int to,int a,int b){e[++co]=(node){next,to,a,b};}
	inline void krus(){
		std::sort(e+1,e+m+1);
		F(i,1,n)fa[i]=i;
		int cnt=0;
		int ansa=0,ansb=0;
		F(i,1,m){
			int fx=find(e[i].u),fy=find(e[i].v);
			if(fx!=fy){
				fa[fy]=fx,cnt++;
				ansa+=e[i].a;
				ansb+=e[i].b;
				if(cnt==n-1)break;
			}
		}ans=max(ans,sqrt(ansa*ansa+ansb*ansb));
	}
	inline short main(){
		file();
		n=read(),m=read();
		F(i,1,m){
			int u=read(),v=read(),a=read(),b=read();
			add(u,v,a,b);
		}
		F(i,1,m)F(j,i+1,m){
			if(e[i].b==e[j].b)continue;
			jiao[++cou]=atan((db)(e[j].a-e[i].a)/(db)(e[i].b-e[j].b));
			cou++;jiao[cou]=jiao[cou-1]+pai;
		}jiao[++cou]=pai/2,jiao[++cou]=pai*1.5;
		std::sort(jiao+1,jiao+cou+1);
		F(i,1,cou-1){
			db jia=(jiao[i]+jiao[i+1])/2.0;
			F(j,1,m){
				db aa=e[j].a*cos(jia),bb=e[j].b*sin(jia);
				e[j].val=aa+bb;
			}krus();
			jia+=pai;
			F(j,1,m){
				db aa=e[j].a*cos(jia),bb=e[j].b*sin(jia);
				e[j].val=aa+bb;
			}krus();
		}
		db jia=(jiao[cou]+jiao[1])/2.0;
		F(i,1,m){
			db aa=e[i].a*cos(jia),bb=e[i].b*sin(jia);
			e[i].val=aa+bb;
		}krus();
		pi(ans);
		return 0;
	}
}
signed main(){return EMT::main();}

Skip

CDQ分治维护单调栈,(数据)点分治

Code


#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define int long long
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("skip.in","r",stdin);freopen("skip.out","w",stdout);}
	inline ll max(ll a,ll b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(ll x){pf("%lld ",x);}inline void pn(){pf("\n");}
	const int N=1e5+10;ll pre[N],f[N],a[N];
	struct pt{int plc,a;ll f;}p[N],s[N];
	inline bool com(pt a,pt b){return a.plc<b.plc;}
	int n,hd,tl;
	inline bool com1(pt a,pt b){return a.a==b.a?a.plc<b.plc:a.a<b.a;}
	inline db lop(pt j,pt k){return (db)(k.f*2-k.plc*k.plc-k.plc+j.plc*j.plc+j.plc-2*j.f)/(db)(2*j.plc-2*k.plc);}
	inline int len(int l,int r){return r-l+1;}
	inline void cdq(int l,int r){
		if(l==r)return;
		int mid=(l+r)>>1;
		cdq(l,mid);
		std::sort(p+l,p+mid+1,com);std::sort(p+mid+1,p+r+1,com);
		int j=l;hd=1;tl=0;
		F(i,mid+1,r){
			while(p[j].plc<p[i].plc&&j<=mid){
				while(tl>1&&lop(s[tl],s[tl-1])>lop(p[j],s[tl]))tl--;
				s[++tl]=p[j];j++;
			}
			int ttl=tl;
			while(ttl>1&&lop(s[ttl],s[ttl-1])>i)ttl--;
			p[i].f=max(p[i].f,s[ttl].f-pre[len(s[ttl].plc+1,p[i].plc-1)]+p[i].a);
		}
		std::sort(p+l,p+r+1,com1);
		cdq(mid+1,r);
	}
	inline short main(){
		file();
		n=read();
		F(i,1,n)p[i].a=a[i]=read(),p[i].plc=i;
		F(i,1,n)pre[i]=pre[i-1]+i;
		F(i,1,n)p[i].f=-1ll*(i-1)*i/2+1ll*p[i].a;
		ll ans1=-1e18;
		a[0]=-1e9-10;
		F(i,1,n)f[i]=-1e18;
		if(n>2150){F(i,1,2149)F(j,0,i-1)if(a[i]>=a[j])f[i]=max(f[i],f[j]-pre[len(j+1,i-1)]+a[i]);
					F(i,2150,n)F(j,i-2150,i-1)if(a[i]>=a[j])f[i]=max(f[i],f[j]-pre[len(j+1,i-1)]+a[i]);
		}else F(i,1,n)F(j,0,i-1)if(a[i]>=a[j])f[i]=max(f[i],f[j]-pre[len(j+1,i-1)]+a[i]);
		F(i,0,n)ans1=max(ans1,f[i]-pre[len(i+1,n)]);
		p[0].a=-1e9-10;
		std::sort(p+0,p+n+1,com1);
		cdq(0,n);
		std::sort(p+0,p+n+1,com);
		ll ans=-1e18;
		F(i,0,n)ans=max(ans,p[i].f-pre[len(i+1,n)]);
		pi(max(ans1,ans));
		return 0;
	}
}
signed main(){return EMT::main();}

2021-09-16 19:41:18 星期四
淦,上一个大集合卡展了,写博客写到一半就崩溃,崩溃了好几次了,于是新开了一个

打怪

打正解是不可能打正解的~~
这个是考完了用乱搞贪心水掉的,然后拿沈sir程序造hack数据hack自己结果把沈sir hack了...数据是XIN造的,把我也hack了,本来以为只有自己会无脸测试点分治结果沈sir也来了个if(n<=10)...虽然沈sir不偷懒改改就能过吧...

Code


#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("fittest.in","r",stdin);freopen("fittest.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline ll min(ll a,ll b){return a<b?a:b;}
	inline void pi(ll x){pf("%lld ",x);}inline void pn(){pf("\n");}
	const int N=3e5+10;
	struct pt{
		int cheng;db chu;
		int c,a,d,id;
	}p[N];int n,b,sum;bool vis[N];ll ans=1e18;
	inline bool com(pt a,pt b){return a.cheng==b.cheng?a.a>b.a:a.cheng>b.cheng;}
	inline bool Com(pt a,pt b){return a.chu<b.chu;}
	inline void solve(){
		std::sort(p+1,p+n+1,Com);
		F(i,1,n)F(j,i+1,n){
			vis[i]=vis[j]=1;
			int sum=0;ll aans=0;
			F(k,1,n)if(!vis[k])sum+=p[k].a;
			F(k,1,n)if(!vis[k]){
				sum-=p[k].a;aans+=1ll*p[k].a*p[k].c;
				aans+=1ll*sum*(p[k].c+1);
			}
			vis[i]=vis[j]=0;
			ans=min(ans,aans);
		}pi(ans);
	}
	inline short main(){
		file();
		n=read();b=read();
		F(i,1,n){
			p[i].id=i;
			p[i].a=read(),p[i].d=read();
			sum+=p[i].a;
			p[i].c=(p[i].d-1)/b;
			p[i].cheng=p[i].c*p[i].a;
			p[i].chu=(db)1.0*(p[i].c+1)/(db)p[i].a;
		}
		if(n<=200){solve();return 0;}
		std::sort(p+1,p+n+1,com);
		vis[p[1].id]=vis[p[2].id]=1;
		sum-=p[1].a,sum-=p[2].a;
		std::sort(p+1,p+n+1,Com);ans=0;
		F(i,1,n)if(!vis[p[i].id]){
			sum-=p[i].a;ans+=1ll*p[i].a*p[i].c;
			ans+=1ll*sum*(p[i].c+1);
		}pi(ans);
		return 0;
	}
}
signed main(){return EMT::main();}

选择

首先每个点连接的边<=10,n<=1e3于是可以状压dp,考试时想到了这个,但是不会处理经过根节点的路径和叶子节点的关系,
可以尝试状压表示经过根节点最多路径有几条,尝试删去某个子树,如果删掉之后答案没变,那么可以将这个子树对应的儿子的延伸结点复制过来,其他的就是普通树形dp统计上子树内的路径即可。

Code


#include<cstring>
#include<iostream>
#include<cstdio>
#include<cmath>
#include<vector>
#include<algorithm>
namespace EMT{
	typedef long long ll;typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline void file(){freopen("select.in","r",stdin);freopen("select.out","w",stdout);}
	inline int max(int a,int b){return a>b?a:b;}inline int min(int a,int b){return a<b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	const int N=1e3+10;
	int head[N],co,n,m,id[N];
	int f[N][1<<10],dp[N];
	struct pair{int a,b;};
	bool graph[N][N];pair rec[N];int cnt,Rec[N],Cnt;
	std::vector<int>son[N],touch[N];
	struct node{
		int next,to;
	}e[N<<1];
	inline void add(int next,int to){e[++co]=(node){head[next],to};head[next]=co;}
	inline void dfs1(int k,int fa){
		int tot=0;
		for(register int i=head[k],j;i;i=e[i].next){
			if((j=e[i].to)==fa)continue;
			++tot;son[k].push_back(j);
			id[j]=tot;
			dfs1(j,k);
		}
	}
	inline void dfs(int k){
		touch[k].push_back(k);
		for(auto j:son[k])dfs(j),dp[k]+=dp[j];
		cnt=Cnt=0;
		for(auto i:son[k])
			for(auto j:son[k])if(id[i]<id[j]){
				for(auto l:touch[i])
					for(auto o:touch[j])
						if(graph[l][o])
							{rec[++cnt]=(pair){i,j};goto ed;}
				ed:;
			}
		for(auto i:son[k])
			for(auto j:touch[i])
				if(graph[k][j])Rec[++Cnt]=i;
		int maxn=0;
		F(i,0,(1<<son[k].size())-1){
			maxn=max(maxn,f[k][i]);
			F(j,1,cnt){
				int u=rec[j].a,v=rec[j].b;
				if(i&(1<<(id[u]-1))||i&(1<<(id[v]-1)))continue;
				f[k][i|(1<<(id[u]-1))|(1<<(id[v]-1))]=max(f[k][i|(1<<(id[u]-1))|(1<<(id[v]-1))],f[k][i]+1);
			}
			F(j,1,Cnt){
				int u=Rec[j];
				if(i&(1<<(id[u]-1)))continue;
				f[k][i|(1<<(id[u]-1))]=max(f[k][i|(1<<(id[u]-1))],f[k][i]+1);
			}
		}dp[k]+=maxn;
		for(auto x:son[k]){
			int Maxn=0;
			F(i,0,(1<<son[k].size())-1)f[k][i]=0;
			F(i,0,(1<<son[k].size())-1){
				Maxn=max(Maxn,f[k][i]);
				F(j,1,cnt){
					int u=rec[j].a,v=rec[j].b;
					if(u==x||v==x)continue;
					if(i&(1<<(id[u]-1))||i&(1<<(id[v]-1)))continue;
					f[k][i|(1<<(id[u]-1))|(1<<(id[v]-1))]=max(f[k][i|(1<<(id[u]-1))|(1<<(id[v]-1))],f[k][i]+1);
				}
				F(j,1,Cnt){
					int u=Rec[j];
					if(u==x)continue;
					if(i&(1<<(id[u]-1)))continue;
					f[k][i|(1<<(id[u]-1))]=max(f[k][i|(1<<(id[u]-1))],f[k][i]+1);
				}
			}
			if(Maxn==maxn)for(auto i:touch[x])touch[k].push_back(i);
		}
	}
	inline short main(){
		file();
		n=read();
		F(i,1,n-1){
			int x=read(),y=read();
			add(x,y);add(y,x);
		}dfs1(1,0);
		m=read();
		F(i,1,m){
			int u=read(),v=read();
			graph[u][v]=graph[v][u]=1;
		}dfs(1);
		pi(dp[1]);
		return 0;
	}
}
signed main(){return EMT::main();}

posted @ 2021-09-27 21:13  letitdown  阅读(224)  评论(8编辑  收藏  举报