省选联测32
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\)
点击查看代码
// 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;