首页 > 其他分享 >省选联测32

省选联测32

时间:2023-02-14 18:44:30浏览次数:51  
标签:Opt return 省选 32 Rep son int 联测 define

nnd考不动了,脑子不转了已经

A.光明

正解做法是\(O(n)\)的,长剖一下,在链上差分贡献,但是貌似常数极大,不知道为啥开六秒。
赛时写的是两个log的二分加启发式,实际表现和\(O(n)\)没什么差别,这题最大的问题还是在内存访问上,一个log的那些做法很容易挂在内存访问上。

俩log
// ubsan: undefined
// accoders
#include <bits/stdc++.h>
typedef long long ll;typedef unsigned long long ull; typedef double db;typedef long double ldb;
#define fre(x) freopen(#x ".in","r",stdin),freopen(#x ".out","w",stdout)
#define Rep(i,a,b) for(int i=a;i<=b;++i) 
#define Dwn(i,a,b) for(int i=a;i>=b;--i)
#define pii pair<int,int>
#define mair make_pair
#define fir first
#define sec second
using namespace std;

const int maxn=3e6+10;
	
char buf[1<<21],*p1,*p2;
char gc(){return p1==p2&&(p2=(p1=buf)+fread(p1=buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
int read(){ int x=0;bool f=0;char c=gc(); while(!isdigit(c)){if(c=='-')f=1;c=gc();} while(isdigit(c))x=x*10+(c^48),c=gc(); return f ? -x : x; }
ll readll(){ ll x=0;bool f=0;char c=gc(); while(!isdigit(c)){if(c=='-')f=1;c=gc();} while(isdigit(c))x=x*10+(c^48),c=gc(); return f ? -x : x; }

int tub[maxn];
ll Allsum,Allcnt;
ll sum[maxn],cnt[maxn];
int Opt[maxn*23],top;
int son[maxn];
int Tar,Lim;
int n;ll K;
int Tc;
void Add(int x){ ++tub[x];(tub[x]==Lim) && (++cnt[Tar]); }
void TAdd(int x){ ++tub[x];(tub[x]==Lim && (++cnt[Tar])),(tub[x] == Lim && (sum[Tar]+=Lim)),(tub[x] > Lim && (++sum[Tar])); }

struct Graph{
	struct eg{ int to,next; }e[maxn];
	int len,head[maxn];
	void lqx(int from,int to)
	{ e[++len].to=to,e[len].next=head[from],head[from]=len; }
	int siz[maxn],dep[maxn],dfn[maxn],rk[maxn],Te;
	void Dfs1(int u){
		siz[u]=1;dfn[u]=++Te;rk[Te]=u;++tub[dep[u]];
		for(int i=head[u];i;i=e[i].next){int v=e[i].to;
			dep[v]=dep[u]+1;Dfs1(v);siz[u]+=siz[v];
			if(!son[u] || siz[v]>siz[son[u]])son[u]=v;
		}
	}
	
	void PrePush(int u){ int R=dfn[u]+siz[u]-1;Rep(i,dfn[u],R)Opt[++top]=(dep[rk[i]]); }
	void PreDel(int u){  int R=dfn[u]+siz[u]-1;Rep(i,dfn[u],R)Opt[++top]=(-dep[rk[i]]); }
	void PreGet(int u,bool Cl){
		for(int i=head[u];i;i=e[i].next)if(e[i].to!=son[u])PreGet(e[i].to,true);
		if(son[u])PreGet(son[u],false);
		Opt[++top]=(n+u);
		Opt[++top]=(dep[u]);
		for(int i=head[u];i;i=e[i].next)if(e[i].to!=son[u])PrePush(e[i].to);
		if(Cl)PreDel(u);
	}
}G;

void Get(int x){ 
	Lim=x;Allcnt=Allsum=0; 
	Rep(i,1,top){
		if(Opt[i]<0)--tub[-Opt[i]];
		else if(Opt[i]>n)cnt[Opt[i]-n]=cnt[son[Opt[i]-n]],Tar=Opt[i]-n;
		else Add(Opt[i]);
	}
	Rep(i,1,n)Allcnt+=cnt[i];
}
void TGet(int x){ 
	Lim=x;Allcnt=Allsum=0; 
	Rep(i,1,top){
		if(Opt[i]<0)--tub[-Opt[i]];
		else if(Opt[i]>n)sum[Opt[i]-n]=sum[son[Opt[i]-n]],cnt[Opt[i]-n]=cnt[son[Opt[i]-n]],Tar=Opt[i]-n;
		else TAdd(Opt[i]);
	}
	Rep(i,1,n)Allsum+=sum[i],Allcnt+=cnt[i];
}

void solve(){
	n=read(),K=readll();Rep(i,2,n){ int x;x=read();G.lqx(x,i); }
	G.dep[1]=1;G.Dfs1(1);Rep(i,1,n)Tc=max(Tc,tub[i]),tub[i]=0;
	G.PreGet(1,1);
	TGet(1);
	if(Allcnt<=K)return printf("%lld\n",Allsum),void();
	int l=1,r=Tc+1;
	while(r-l>1){
		int mid=(l+r)>>1;Get(mid);
		if(Allcnt>K)l=mid;
		else r=mid;
	}TGet(r);
	printf("%lld\n",(Allsum+(K-Allcnt)*(r-1)));
}

int main (){
	fre(light);
	return solve(),0; 
}

cgy的线性
// ubsan: undefined
// accoders
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define getc() p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;
char buf[1<<21],*p1,*p2,ch;
ll read(){
	ll ret=0;char c=getc();
	while(c<'0'||c>'9')c=getc();
	while(c>='0'&&c<='9')ret=ret*10+c-'0',c=getc();
	return ret;
}
const int maxn = 3e6 + 55;
ll n, k, cnt[maxn];
int fa[maxn], dep[maxn], mxd[maxn], son[maxn];
vector<int>g[maxn], f[maxn];
int main(){
	freopen("light.in","r",stdin);
	freopen("light.out","w",stdout);
	n = read(), k = read(); dep[1] = 1;
	for(int i = 2; i <= n; ++i)g[fa[i] = read()].push_back(i), dep[i] = dep[fa[i]] + 1;
	for(int i = n; i >= 1; --i){
		if(!mxd[i])mxd[i] = dep[i];
		if(mxd[fa[i]] < mxd[i])mxd[fa[i]] = mxd[i], son[fa[i]] = i;
	}
	for(int x = n; x >= 1; --x){
		if(son[x])swap(f[x], f[son[x]]);
		int en = f[x].size();
		for(int v : g[x])if(v != son[x]){
			int s = f[v].size();
			for(int i = 1; i <= s; ++i){
				cnt[f[v].back()] -= dep[x];
				cnt[f[x][en - i]] -= dep[x];
				f[x][en - i] += f[v].back();
				cnt[f[x][en - i]] += dep[x];
				f[v].pop_back();
			}
		}
		f[x].push_back(1);  cnt[1] += dep[x];
	}
	ll ans = 0;
	for(int i = n; i >= 1; --i)
		if(cnt[i] < k){
			ans += cnt[i] * i;
			k -= cnt[i];
		}else{
			ans += i * k;
			break;
		}
	
	printf("%lld\n",ans);
	return 0;
}

B.游戏

考虑两人一定会选同一段,赢当且仅当段长大于等于\(2k-1\)。于是就是算存在至少一个这样的段的方案数。正难则反一下就是求极长连续段最长不超过\(2k-2\)的方案数。算了直接粘题解了

递推式并不会推,但是那一部分可以用解5直接草过去
题解有一个地方的指数多了个\(k\)

image
image
image

点击查看代码
// ubsan: undefined
// accoders
#include <bits/stdc++.h>
typedef long long ll;typedef unsigned long long ull; typedef double db;typedef long double ldb;
#define fre(x) freopen(#x ".in","r",stdin),freopen(#x ".out","w",stdout)
#define Rep(i,a,b) for(int i=a;i<=b;++i) 
#define Dwn(i,a,b) for(int i=a;i>=b;--i)
#define pii pair<int,int>
#define mair make_pair
#define fir first
#define sec second
using namespace std;

const int maxn=4e2+10,M=1e7+30;

int Mod,V;
int n,m,K;

int pw(int x,int p){int res=1,base=x;while(p){if(p&1)res=1LL*res*base%Mod;base=1LL*base*base%Mod;p>>=1;}return res;}
int Inv(int x){return pw(x,Mod-2);}

struct Matrix{
	ll a[maxn][maxn];
	Matrix(){memset(a,0,sizeof(a));}
	void Clear(){memset(a,0,sizeof(a));}
	void Init(){Rep(i,1,V)a[i][i]=1;}
	friend Matrix operator * (const Matrix &x,const Matrix &y){
		Matrix z;
		Rep(i,1,V)Rep(k,1,V)
		{ ll r=x.a[i][k];  if(r)Rep(j,1,V)(y.a[k][j]) && (z.a[i][j]+=r*y.a[k][j]); }
		Rep(i,1,V)Rep(j,1,V)z.a[i][j]%=Mod;
		return z;
	}
	Matrix Pow(int p){
		Matrix res,base=(*this);res.Init();
		while(p){if(p&1)res=res*base;p>>=1;base=base*base;}
		return res;
	}
	void Print(){Rep(i,1,V){ Rep(j,1,V)cout<<a[i][j]%Mod<<" ";cout<<" ";} }
}F,G;

void Sol1(){
	F.a[1][1]=m;Rep(i,2,K)F.a[1][i]=1LL*F.a[1][i-1]*m%Mod;
	F.a[1][K]=(F.a[1][K]-m)%Mod;
	Rep(i,2,K)G.a[i][i-1]=1;
	G.a[K][K]=m;G.a[1][K]=-(m-1);
	if(n<=K)return cout<<((pw(m,n)-F.a[1][n])%Mod+Mod)%Mod<<"\n",void();
	if(K<n)F=F*(G.Pow(n-K));
	cout<<((pw(m,n)-F.a[1][K])%Mod+Mod)%Mod<<"\n";
}

int fac[M],inv[M];
void Init(int n=0){
	n=Mod-1;
	fac[0]=inv[0]=1;Rep(i,1,n)fac[i]=1LL*fac[i-1]*i%Mod;
	inv[n]=Inv(fac[n]);Dwn(i,n-1,1)inv[i]=1LL*inv[i+1]*(i+1)%Mod;
}
int C(int n,int m){ if(n<m)return 0;return 1LL*fac[n]*inv[m]%Mod*inv[n-m]%Mod; }
int Lucas(int n,int m){
	if(n<m)return 0;
	if(n<Mod)return C(n,m);
	return 1LL*Lucas(n/Mod,m/Mod)*C(n%Mod,m%Mod)%Mod;
}

int A[M];

void Sol2(){
	Init();A[0]=1;for(int i=1;i<Mod;++i)A[i]=1LL*A[i-1]*m%Mod;
	int res=0,p=n-1,pk=1;
	for(int i=0;1LL*i*K<=p;++i){
		res=(res-1LL*Lucas(p-i*(K-1),i)*pk%Mod*A[(p-i*K)%(Mod-1)])%Mod;
		pk=1LL*pk*(1-m)%Mod;
	}
	p=n,pk=1;
	for(int i=0;1LL*i*K<=p;++i){
		res=(res+1LL*Lucas(p-i*(K-1),i)*pk%Mod*A[(p-i*K)%(Mod-1)])%Mod;
		pk=1LL*pk*(1-m)%Mod;
	}
	res=(1LL*res*m%Mod*Inv(m-1)%Mod+Mod)%Mod;
	cout<<((pw(m,n)-res)%Mod+Mod)%Mod<<"\n";
}

void solve(){
	cin>>n>>m>>K>>Mod;V=2*K-1;K=V;

	if(K==1)return cout<<pw(m,n)<<"\n",void();
	if(K>n)return cout<<0<<"\n",void();
	if(K<=400)return Sol1();
	return Sol2();
}

int main (){ fre(game);ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);return solve(),0; }

C.皇后

随机化,乱搞

点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int a[N];
bool vis[N];
int n;
bool check(int len){
        for(int i = 1; i < len; ++i){
                if(abs(i - len) == abs(a[i] - a[len])) return false;
                // if(a[i] - i == a[len] - len) return false;
        }
        return true;
}
void search(int pos){
        if(check(pos - 1) == false) return;
        if(pos == n + 1){
                static bool fake[N][N] = {};
                for(int i = 1; i <= n; ++i){
                        cout << i <<" " << a[i] << "\n";
                }
                cout <<endl;
                exit(0);
                return;
        }

        if(pos > 1 && a[pos - 1] + 2 <= n && vis[a[pos - 1] + 2] == false && vis[n] == false){
                int val = a[pos - 1] + 2;
                a[pos] = val;
                vis[val] = true;
                search(pos + 1);
                vis[val] = false;
        }
        for(int i = 1; i <= n; ++i){
                if(vis[i]) continue;
                a[pos] = i;
                vis[i] = true;
                search(pos + 1);
                vis[i] = false;
                a[pos] = 0;
        }
}
int main(){
        cin >> n;
        // a[1] = 2, vis[1] = true;
        // a[1] = 1, a[2] = 3, a[3] = 5, a[4] = 7;
        // vis[1] = true, vis[3] = true, vis[5] = true, vis[7] = true;
        if(n % 2 == 0){
                a[1] = 2;
                vis[2] = true;
                search(2);
        }else{
                a[1] = 1;
                vis[1] = true;
                search(2);
        }
        return 0;

标签:Opt,return,省选,32,Rep,son,int,联测,define
From: https://www.cnblogs.com/Delov/p/17120579.html

相关文章