190911 CSP-S 2019模拟

A

d d dd dd长链剖分与辣鸡 W O J WOJ WOJ
代码:

#include
#define ri register int
#define fi first
#define se second
#define pb push_back
using namespace std;
const int rlen=1<<18|1;
char buf[rlen],*ib=buf,*ob=buf;
#define gc() (((ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin)),ib==ob)?-1:*ib++)
typedef pair<int,int> pii;
typedef long long ll;
inline int read(){
	int ans=0;
	char ch=gc();
	while(!isdigit(ch))ch=gc();
	while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
	return ans;
}
const int mod=998244353;
inline int add(int a,int b){return (a+=b)<mod?a:a-mod;}
inline int dec(int a,int b){return (a-=b)<0?a+mod:a;}
inline int mul(int a,int b){return (ll)a*b%mod;}
inline void Add(int&a,int b){(a+=b)<mod?a:(a-=mod);}
inline void Dec(int&a,int b){(a-=b)<0?(a+=mod):a;}
inline void Mul(int&a,int b){a=(ll)a*b%mod;}
inline int ksm(int a,int p){int ret=1;for(;p;p>>=1,Mul(a,a))if(p&1)Mul(ret,a);return ret;}
const int N=1e6+5;
namespace sgt{
	#define lc (p<<1)
	#define rc (p<<1|1)
	#define mid (l+r>>1)
	ll mx[N<<2],add[N<<2];
	inline void pushnow(int p,ll v){add[p]+=v,mx[p]+=v;}
	inline void pushdown(int p){(add[p])&&(pushnow(lc,add[p]),pushnow(rc,add[p]),add[p]=0);}
	inline void update(int p,int l,int r,int k,ll v){
		if(l==r){mx[p]=max(mx[p],v);return;}
		pushdown(p);
		k<=mid?update(lc,l,mid,k,v):update(rc,mid+1,r,k,v);
		mx[p]=max(mx[lc],mx[rc]);
	}
	inline void modify(int p,int l,int r,int ql,int qr,ll v){
		if(ql<=l&&r<=qr)return pushnow(p,v);
		pushdown(p);
		if(qr<=mid)modify(lc,l,mid,ql,qr,v);
		else if(ql>mid)modify(rc,mid+1,r,ql,qr,v);
		else modify(lc,l,mid,ql,qr,v),modify(rc,mid+1,r,ql,qr,v);
		mx[p]=max(mx[lc],mx[rc]);
	}
	inline ll query(int p,int l,int r,int ql,int qr){
		if(ql<=l&&r<=qr)return mx[p];
		pushdown(p);
		if(qr<=mid)return query(lc,l,mid,ql,qr);
		else if(ql>mid)return query(rc,mid+1,r,ql,qr);
		return max(query(lc,l,mid,ql,qr),query(rc,mid+1,r,ql,qr));
	}
	#undef lc
	#undef rc
	#undef mid
}
inline void ckmax(ll&a,ll b){a=a>b?a:b;}
int n,fa[N],dep[N],mxdep[N],hson[N],len[N],L[N],R[N];
ll ans[N];
int pred[N],num[N],tot=0;
vector<pii>e[N];
void dfs1(int p){
	mxdep[p]=dep[p];
	for(ri i=0,v;i<e[p].size();++i){
		dep[v=e[p][i].fi]=dep[p]+1,dfs1(v),mxdep[p]=max(mxdep[p],mxdep[v]);
		if(mxdep[p]==mxdep[v])hson[p]=v;
	}
	len[p]=mxdep[p]-dep[p];
}
void dfs2(int p){
	pred[num[p]=++tot]=p;
	if(!hson[p])return;
	dfs2(hson[p]);
	for(ri i=0,v;i<e[p].size();++i)if((v=e[p][i].fi)!=hson[p])dfs2(v);
}
void dfs3(int p){
	if(!hson[p])return;
	if(hson[p])dfs3(hson[p]);
	for(ri i=0;i<e[p].size();++i)if(e[p][i].fi==hson[p])sgt::modify(1,1,n,num[p]+1,num[p]+len[p],e[p][i].se);
	ll upd;
	for(ri i=0,v;i<e[p].size();++i){
		if((v=e[p][i].fi)==hson[p])continue;
		dfs3(v);
		for(ri j=0;j<=len[v];++j){
			upd=sgt::query(1,1,n,num[v]+j,num[v]+j)+e[p][i].se;
			if(L[p]<=j+1+len[p]&&j+1<=R[p])ans[p]=max(ans[p],upd+sgt::query(1,1,n,num[p]+max(0,L[p]-j-1),num[p]+min(len[p],R[p]-j-1)));
		}
		for(ri j=0;j<=len[v];++j){
			upd=sgt::query(1,1,n,num[v]+j,num[v]+j)+e[p][i].se;
			sgt::update(1,1,n,num[p]+j+1,upd);
		}
	}
	if(len[p]>=L[p])ckmax(ans[p],sgt::query(1,1,n,num[p]+L[p],num[p]+min(R[p],len[p])));
}
int main(){
	int size=100<<20;//40M
    __asm__ ("movq %0,%%rsp\n"::"r"((char*)malloc(size)+size));//提交用这个 
	n=read();
	for(ri i=1;i<=n;++i)L[i]=read(),R[i]=read(),ans[i]=-1;
	for(ri i=2;i<=n;++i)fa[i]=read(),e[fa[i]].pb(pii(i,read()));
	dep[1]=1,dfs1(1),dfs2(1);
	dfs3(1);
	int res=0;
	for(ri i=n,mt=1;i;--i,Mul(mt,23333))Add(res,mul(mt,(ans[i]%mod+mod)%mod));
	cout<<res;
	exit(0);
}

B

三道题里面最容易的一道
d d dd dd 仙人掌 d p dp dp 与辣鸡标算,直接考虑对每个环分别 d p dp dp 即可
代码:

#include
#define ri register int
#define fi first
#define se second
#define pb push_back
using namespace std;
const int rlen=1<<18|1;
char buf[rlen],*ib=buf,*ob=buf;
#define gc() (((ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin)),ib==ob)?-1:*ib++)
typedef pair<int,int> pii;
typedef long long ll;
inline int read(){
	int ans=0;
	char ch=gc();
	while(!isdigit(ch))ch=gc();
	while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
	return ans;
}
const int mod=998244353;
inline int add(int a,int b){return (a+=b)<mod?a:a-mod;}
inline int dec(int a,int b){return (a-=b)<0?a+mod:a;}
inline int mul(int a,int b){return (ll)a*b%mod;}
inline void Add(int&a,int b){(a+=b)<mod?a:(a-=mod);}
inline void Dec(int&a,int b){(a-=b)<0?(a+=mod):a;}
inline void Mul(int&a,int b){a=(ll)a*b%mod;}
inline int ksm(int a,int p){int ret=1;for(;p;p>>=1,Mul(a,a))if(p&1)Mul(ret,a);return ret;}
const int N=1e6+5;
namespace sgt{
	#define lc (p<<1)
	#define rc (p<<1|1)
	#define mid (l+r>>1)
	ll mx[N<<2],add[N<<2];
	inline void pushnow(int p,ll v){add[p]+=v,mx[p]+=v;}
	inline void pushdown(int p){(add[p])&&(pushnow(lc,add[p]),pushnow(rc,add[p]),add[p]=0);}
	inline void update(int p,int l,int r,int k,ll v){
		if(l==r){mx[p]=max(mx[p],v);return;}
		pushdown(p);
		k<=mid?update(lc,l,mid,k,v):update(rc,mid+1,r,k,v);
		mx[p]=max(mx[lc],mx[rc]);
	}
	inline void modify(int p,int l,int r,int ql,int qr,ll v){
		if(ql<=l&&r<=qr)return pushnow(p,v);
		pushdown(p);
		if(qr<=mid)modify(lc,l,mid,ql,qr,v);
		else if(ql>mid)modify(rc,mid+1,r,ql,qr,v);
		else modify(lc,l,mid,ql,qr,v),modify(rc,mid+1,r,ql,qr,v);
		mx[p]=max(mx[lc],mx[rc]);
	}
	inline ll query(int p,int l,int r,int ql,int qr){
		if(ql<=l&&r<=qr)return mx[p];
		pushdown(p);
		if(qr<=mid)return query(lc,l,mid,ql,qr);
		else if(ql>mid)return query(rc,mid+1,r,ql,qr);
		return max(query(lc,l,mid,ql,qr),query(rc,mid+1,r,ql,qr));
	}
	#undef lc
	#undef rc
	#undef mid
}
inline void ckmax(ll&a,ll b){a=a>b?a:b;}
int n,fa[N],dep[N],mxdep[N],hson[N],len[N],L[N],R[N];
ll ans[N];
int pred[N],num[N],tot=0;
vector<pii>e[N];
void dfs1(int p){
	mxdep[p]=dep[p];
	for(ri i=0,v;i<e[p].size();++i){
		dep[v=e[p][i].fi]=dep[p]+1,dfs1(v),mxdep[p]=max(mxdep[p],mxdep[v]);
		if(mxdep[p]==mxdep[v])hson[p]=v;
	}
	len[p]=mxdep[p]-dep[p];
}
void dfs2(int p){
	pred[num[p]=++tot]=p;
	if(!hson[p])return;
	dfs2(hson[p]);
	for(ri i=0,v;i<e[p].size();++i)if((v=e[p][i].fi)!=hson[p])dfs2(v);
}
void dfs3(int p){
	if(!hson[p])return;
	if(hson[p])dfs3(hson[p]);
	for(ri i=0;i<e[p].size();++i)if(e[p][i].fi==hson[p])sgt::modify(1,1,n,num[p]+1,num[p]+len[p],e[p][i].se);
	ll upd;
	for(ri i=0,v;i<e[p].size();++i){
		if((v=e[p][i].fi)==hson[p])continue;
		dfs3(v);
		for(ri j=0;j<=len[v];++j){
			upd=sgt::query(1,1,n,num[v]+j,num[v]+j)+e[p][i].se;
			if(L[p]<=j+1+len[p]&&j+1<=R[p])ans[p]=max(ans[p],upd+sgt::query(1,1,n,num[p]+max(0,L[p]-j-1),num[p]+min(len[p],R[p]-j-1)));
		}
		for(ri j=0;j<=len[v];++j){
			upd=sgt::query(1,1,n,num[v]+j,num[v]+j)+e[p][i].se;
			sgt::update(1,1,n,num[p]+j+1,upd);
		}
	}
	if(len[p]>=L[p])ckmax(ans[p],sgt::query(1,1,n,num[p]+L[p],num[p]+min(R[p],len[p])));
}
int main(){
	n=read();
	for(ri i=1;i<=n;++i)L[i]=read(),R[i]=read(),ans[i]=-1;
	for(ri i=2;i<=n;++i)fa[i]=read(),e[fa[i]].pb(pii(i,read()));
	dep[1]=1,dfs1(1),dfs2(1);
	dfs3(1);
	int res=0;
	for(ri i=n,mt=1;i;--i,Mul(mt,23333))Add(res,mul(mt,(ans[i]%mod+mod)%mod));
	cout<<res;
	exit(0);
}

C

在听了拥有 6 , 7 6,7 6,7 个后宫(亲口说出),每天切 i n f inf inf 道神题并且天天假自己爆零的数论之神 B . S B.S B.S 的讲解之后终于会了
其实就是化成 c , d , p c,d,p c,d,p 两两都互质的情况然后就能类欧几里得转化了
代码:

#include
#define ri register int
#define pb push_back
using namespace std;
const int rlen=1<<18|1;
char buf[rlen],*ib=buf,*ob=buf;
#define gc() (((ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin)),ib==ob)?-1:*ib++)
typedef long long ll;
inline int read(){
	int ans=0;
	char ch=gc();
	while(!isdigit(ch))ch=gc();
	while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
	return ans;
}
const int mogic=6e6+5;
struct Hash_table{
	vector<int>ori[mogic],vl[mogic];
	inline void insert(int x,int v){
		int t=x%mogic;
		ori[t].pb(x),vl[t].pb(v);
	}
	inline int query(int x){
		for(ri t=x%mogic,i=ori[t].size()-1;~i;--i)if(ori[t][i]==x)return vl[t][i];
		return -1;
	}
}S;
int mod,P,g;
inline int add(int a,int b){return (a+=b)<mod?a:a-mod;}
inline int dec(int a,int b){return (a-=b)<0?a+mod:a;}
inline int mul(int a,int b){return (ll)a*b%mod;}
inline void Add(int &a,int b){(a+=b)<mod?0:a-=mod;}
inline void Dec(int &a,int b){(a-=b)<0?a+=mod:0;}
inline void Mul(int &a,int b){a=(ll)a*b%mod;}
inline int ksm(int a,int b,int res=1){for(;b;b>>=1,Mul(a,a))(b&1)&&(Mul(res,a),1);return res;}
inline int Inv(int x){return ksm(x,mod-2);}
int blo,V=1;
inline void init(){for(ri i=0;i<blo;i++)S.insert(V,i),Mul(V,g);}
inline int solve(int k){k=Inv(k);for(ri t,i=0;i<blo;i++,Mul(k,V))if(~(t=S.query(k)))return ((ll)(i*blo-t)%P+P)%P;}
int pr[1005],tot,n;
inline bool check(int k){for(ri i=1,phi=mod-1;i<=tot;i++)if(ksm(k,phi/pr[i])==1)return 1;return 0;}
inline void find_g(int phi=mod-1){
	for(ri i=2;i*i<=phi;i++){
		if(phi==1)break;
		if(phi!=phi/i*i)continue;
		pr[++tot]=i;
		while(phi==phi/i*i)phi/=i;
	}
	if(phi^1)pr[++tot]=phi;
	g=2;
	while(check(g))++g;
}
inline void exgcd(ll &x,ll &y,ll a,ll b){if(!b){x=1,y=0;return;}exgcd(y,x,b,a%b),y-=a/b*x;}
inline ll Inv2(ll t,ll x=0,ll y=0){return exgcd(x,y,t,P),(x%P+P)%P;}
inline ll gcd(ll a,ll b,ll t=0){while(b)t=a,a=b,b=t-t/a*a;return a;}
const ll inf=1e18;
inline ll f(int l,int r,ll a,ll b,ll c,ll d,ll e){
	if(l>r)return inf;
	ll L=(c*l+d)/e,R=(c*r+d)/e;
	if(L==R)return min(a*l,a*r)+b*R;
	if(c>=e)return f(l,r,a+b*(c/e),b,c%e,d,e);
	if(a>=0)return min(a*l+b*L,f(L+1,R,b,a,e,c-d-1,c));
	return min(a*r+b*R,f(L,R-1,b,a,e,e-d-1,c));
}
int main(){
	#ifdef ldxcaicai
	freopen("lx.in","r",stdin);
	#endif
	mod=read(),P=mod-1,n=read();
	blo=sqrt((ll)n*mod)+1;
	find_g();
	init();
	for(ll g,a,b,c,d;n;--n){
		a=read(),b=read(),c=read()%mod,d=read()%mod;P=mod-1;
		if(!c||!d){puts("Damn it");continue;}
		c=solve(c),d=solve(d),g=gcd(gcd(c,d),P),c/=g,d/=g,P/=g;
		g=gcd(c,P),c/=g,P/=g,b*=g;
		c&&(d=(ll)d*Inv2(c)%P);
		g=gcd(d,P),a*=g,d/=g,P/=g;
		cout<<min((ll)P*(a+b),f(1,P-1,(ll)a*d+b,-a*P,d,0,P))<<'\n';
	}
	return 0;
}

你可能感兴趣的:(#,题解)