SDOI2018

去ctsc和apio的时候就听山东妹子说SD round2的题一般不是很可做

这套题充分体现了Serene的sb程度无人可比

 

D1T1物理实验

一看就是计算几何题,对码力要求有点高,让我想起了SCOI我炸的那道计算几何题

感觉这个还没有SCOID2T2复杂?

反正现在还没码出来,准确来说是暂时不想码,码到一半,有时间再码完

 

D1T2战略游戏

看了一会,大概想到了什么点双,什么一个点双向其包含的点连边

竟然没发现这就是圆方树?

我真是如此智障……

圆方树,对于每个询问建虚树

我点双的板子又写错了,前几天还刚写过来着……为此调了一天,真是太sb了

//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<set>
using namespace std;
#define ll long long
#define db double
#define For(i,a,b) for(int i=(a);i<=(b);++i)
#define Rep(i,a,b) for(int i=(a);i>=(b);--i)
const int maxn=4e5+7,maxt=23,W=19;
int Td,n,m,Q,k,p[maxn];

char cc;ll ff;
template<typename T>void read(T& aa) {
    aa=0;ff=1; cc=getchar();
    while(cc!='-'&&(cc<'0'||cc>'9')) cc=getchar();
    if(cc=='-') ff=-1,cc=getchar();
    while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    aa*=ff;
}

int fir[maxn],nxt[2*maxn],to[2*maxn],e=1;
void add(int x,int y) {
    to[++e]=y;nxt[e]=fir[x];fir[x]=e;
    to[++e]=x;nxt[e]=fir[y];fir[y]=e;
}

int FIR[maxn],NXT[2*maxn],TO[2*maxn],E=0;
void ADD(int x,int y) {
//	printf("ADD:%d->%d\n",x,y);
    TO[++E]=y;NXT[E]=FIR[x];FIR[x]=E;
    TO[++E]=x;NXT[E]=FIR[y];FIR[y]=E;
}

int dfn[maxn],end[maxn],low[maxn],dfn_clock;
int zz[maxn],top,toth;
set<int> G;
set<int>::iterator it;
void tj(int pos) {
    dfn[pos]=low[pos]=++dfn_clock;
    int y,z,bot;
    for(y=fir[pos];y;y=nxt[y]) {
        if(dfn[z=to[y]]) {low[pos]=min(low[pos],dfn[z]);continue;}
	    zz[++top]=y; bot=top;
        tj(z); low[pos]=min(low[pos],low[z]);
	    zz[++top]=y^1;
        if(low[z]==dfn[pos]) {
            ++toth; G.clear();
            For(i,bot,top) G.insert(to[zz[i]]);
            for(it=G.begin();it!=G.end();++it) ADD(n+toth,*it);
            top=bot-1;
        }
    }
}

int fa[maxn][maxt],sum[maxn][maxt],dep[maxn];
void dfs(int pos,int f) {
    fa[pos][0]=f; sum[pos][0]=pos<=n;
    dfn[pos]=++dfn_clock; dep[pos]=dep[f]+1;
    For(i,1,W) {
        fa[pos][i]=fa[fa[pos][i-1]][i-1];
        sum[pos][i]=sum[pos][i-1]+sum[fa[pos][i-1]][i-1];
    }
    int y,z;
    for(y=FIR[pos];y;y=NXT[y]) {
        if((z=TO[y])==f) continue;
        dfs(z,pos);
    }
    end[pos]=dfn_clock;
}

bool cmp(const int x,const int y) {return dfn[x]<dfn[y];}

int get_lca(int x,int y) {
    if(dep[x]!=dep[y]) {
        if(dep[x]<dep[y]) swap(x,y);
        Rep(i,W,0) if(dep[fa[x][i]]>=dep[y]) x=fa[x][i];
    }
    if(x==y) return x;
    Rep(i,W,0) if(fa[x][i]!=fa[y][i]) {
        x=fa[x][i]; y=fa[y][i];
    }
    return fa[x][0];
}

int get_sum(int x,int l) {
    int rs=0;
    Rep(i,W,0) if(l>=(1<<i)) {
        l-=(1<<i);
        rs+=sum[x][i];
        x=fa[x][i];
    }
    return rs;
}

int get_ans() {
    int t=k,x,rs=-k;
    sort(p+1,p+k+1,cmp);
    For(i,1,k-1) {
        x=get_lca(p[i],p[i+1]);
        if(x!=p[i]) p[++t]=x;
    }
    k=t; t=0;
    sort(p+1,p+k+1);
    k=unique(p+1,p+k+1)-(p+1);
    sort(p+1,p+k+1,cmp);
    zz[++t]=p[1];rs+=sum[p[1]][0];
    For(i,2,k) {
        x=p[i];
        while(dfn[x]<dfn[zz[t]]||dfn[x]>end[zz[t]]) t--;
        rs+=get_sum(x,dep[x]-dep[zz[t]]);
        zz[++t]=x;
    }
    return rs;
}

void clear() {
    For(i,1,n+toth) fir[i]=FIR[i]=dfn[i]=0;
    E=dfn_clock=top=toth=0; e=1;
}

int main() {
    read(Td); int x,y;
    while(Td--) {
        clear();
        read(n); read(m);
        For(i,1,m) {
            read(x); read(y);
            add(x,y);
        }
        tj(1); dfn_clock=0;
        dfs(1,0);
        read(Q);
        For(i,1,Q) {
            read(k);
            For(j,1,k) read(p[j]);
            printf("%d\n",get_ans());
        }
    }
    return 0;
}

附上rand:

//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<ctime>
using namespace std;
#define ll long long
#define db double
#define For(i,a,b) for(int i=(a);i<=(b);++i)
#define Rep(i,a,b) for(int i=(a);i>=(b);--i)
const int Td=3,N=5,M=5,Q=3,K=5;
int n,m,q,k,p[N+7];

char cc;ll ff;
template<typename T>void read(T& aa) {
	aa=0;ff=1; cc=getchar();
	while(cc!='-'&&(cc<'0'||cc>'9')) cc=getchar();
	if(cc=='-') ff=-1,cc=getchar();
	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
	aa*=ff;
}

int main() {
	srand((unsigned)time(NULL));
	printf("%d\n",Td); int x,y;
	For(cs,1,Td) {
		n=rand()%N+3;
		m=rand()%M+n-1;
		printf("%d %d\n",n,m);
		For(i,1,n) p[i]=i;
		random_shuffle(p+1,p+n+1);
		For(i,2,n) printf("%d %d\n",p[rand()%(i-1)+1],p[i]);
		For(i,n,m) {
			x=y=rand()%n+1; while(x==y) y=rand()%n+1;
			printf("%d %d\n",x,y);
		}
		q=rand()%Q+2; printf("%d\n",q);
		For(i,1,q) {
			k=rand()%min(K,n-1)+2; printf("%d",k);
			random_shuffle(p+1,p+n+1);
			For(j,1,k) printf(" %d",p[j]);
			printf("\n");
		}
	}
	return 0;
}

  

D1T3 反回文串

我一直在想啥子容斥啊,啥子那样的串可能是

1、一个回文串

2、两个偶回文串

3、一个偶回文串+一个奇回文串

大方向都错了,怪不得百思不得其解

一看数据范围就是推式子题,而根据循环节长度来做多有趣的,可以用到sigma把式子列出来。

而我tm是在找规律么,式子都列不出来

感觉这样的题,我考场上永远想不出正解来……

听说要卡log的快速乘,但是我并没有被卡啊,感觉还是蛮快的?

题解:https://www.luogu.org/problemnew/show/P4607

//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<set>
using namespace std;
#define ll long long
#define db long double
#define For(i,a,b) for(int i=(a);i<=(b);++i)
#define Rep(i,a,b) for(int i=(a);i>=(b);--i)
const db eps=1e-8;
const int TM=20,M=120,maxn=23;
ll Td,n,K,mod,p[maxn],sum[maxn],tot;

char cc;ll ff;
template<typename T>void read(T& aa) {
	aa=0;ff=1; cc=getchar();
	while(cc!='-'&&(cc<'0'||cc>'9')) cc=getchar();
	if(cc=='-') ff=-1,cc=getchar();
	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
	aa*=ff;
}

ll gcd(ll x,ll y) {return y==0? x:gcd(y,x%y);}

ll qp(ll x,ll k) {
	ll rs=1; x%=mod;
	while(k) {
		if(k&1) rs=rs*x%mod;
		k>>=1; x=x*x%mod;
	}
	return rs;
}

ll qc(ll x,ll k,ll mod) {
	ll rs=0;
	while(k) {
		if(k&1) rs=(rs+x)%mod;
		k>>=1; x=(x+x)%mod;
	}
	return rs;
}		

ll qp2(ll x,ll k,ll mod) {
	ll rs=1;
	while(k) {
		if(k&1) rs=qc(rs,x,mod);
		k>>=1; x=qc(x,x,mod);
	}
	return rs;
}

bool Miller_Rabin(ll n) {
	if(n==2||n==3||n==5) return 1;
	if(n<2||(n%6!=1&&n%6!=5)) return 0;
	ll m=n-1,t=0,x,y;
	while((m&1)==0) t++,m>>=1;
	For(i,1,TM) {
		x=rand()%(n-1)+1;
		x=qp2(x,m,n);
		For(j,1,t) {
			y=qc(x,x,n);
			if(y==1&&x!=1&&x!=n-1) return 0;
			x=y;
		}
		if(x!=1) return 0;
	}
	return 1;
}

ll prho(ll n,ll m) {
	ll x=rand()%(n-1)+1,y=0;
	for(ll i=1,k=1,d;y!=x;++i) {
		if(i==k) {y=x;k<<=1;}
		x=(qc(x,x,n)+m)%n;
		d=gcd((x-y+n)%n,n);
		if(d>1&&d<n) return d;
	}
	return n;
}

multiset<ll> G;
multiset<ll>::iterator it;

void find(ll n,ll m) {
	if(Miller_Rabin(n)) {
		G.insert(n);
		return;
	}
	ll p=n; while(p>=n) p=prho(n,m--);
	find(p,M); find(n/p,M);
}

ll g(ll x) {return qp(K,(x+1)>>1);}

ll h(ll x) {return (x&1)==1? x:x>>1;}

ll get_ans(ll x) {
	return h(x)%mod*g(x)%mod;
}

ll dfs(int pos,ll now,ll x) {
	ll rs=0;
	if(pos>tot) {
		ll d=n/now;
		if((d&1)&&!(now&1)) rs=0;
		else rs=get_ans(n/now)*x%mod;
//		printf("dfs:%lld: x=%lld,rs=%lld\n",now,x,rs);
		return rs;
	}
	For(i,0,sum[pos]) {
		rs+=dfs(pos+1,now,i? (1-p[pos]%mod+mod)%mod*x%mod:x); rs%=mod;
		now*=p[pos];
	}
	return rs%mod;
} 

void clear() {
	For(i,1,tot) sum[i]=0;
	tot=0; G.clear();
}

int main() {
	read(Td);
	while(Td--) {
		clear();
		read(n); read(K); read(mod);
		if(n!=1) find(n,M);
		for(it=G.begin();it!=G.end();++it) {
			if(*it!=p[tot]) p[++tot]=*it;
			++sum[tot];
		}
		printf("%lld\n",dfs(1,1,1));
	}
//	cerr<<clock()<<"\n";
	return 0;
}

  

D2T1 原题识别

还没看,等着Achen做起了给我讲

 

D2T2 旧试题

听Achen讲这道题,记不起来约数是什么了……

充分体现出自己多么智障

题解:https://www.luogu.org/problemnew/solution/P4619

 

D2T3 荣誉称号

明显一棵完全二叉树的样子,然后发现下面的一堆和上面的同余,可以直接归到上面去dp就好了

//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
#define ll long long
#define db double
#define For(i,a,b) for(int i=(a);i<=(b);++i)
#define Rep(i,a,b) for(int i=(a);i>=(b);--i)
const ll INF=1e16;
const int maxn=(1<<12)+7,maxm=200+7,maxt=1e7+7;
int Td,n,k,m,U,a[maxt],b[maxt];
ll sum[maxn][maxm],v[maxm][maxm],cst[maxn][maxm],dp[maxn][maxm];

char cc;ll ff;
template<typename T>void read(T& aa) {
	aa=0;ff=1; cc=getchar();
	while(cc!='-'&&(cc<'0'||cc>'9')) cc=getchar();
	if(cc=='-') ff=-1,cc=getchar();
	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
	aa*=ff;
}

unsigned int SA, SB, SC;int pd, A, B;
unsigned int rng61(){
    SA ^= SA << 16;
    SA ^= SA >> 5;
    SA ^= SA << 1;
    unsigned int t = SA;
    SA = SB;
    SB = SC;
    SC ^= t ^ SA;
    return SC;
}

void init(){
    scanf("%d%d%d%d%u%u%u%d%d", &n, &k, &m, &pd, &SA, &SB, &SC, &A, &B);
    for(int i = 1; i <= pd; i++)scanf("%d%d", &a[i], &b[i]);
    for(int i = pd + 1; i <= n; i++){
        a[i] = rng61() % A + 1;
        b[i] = rng61() % B + 1;
    }
}

void clear() {
	For(i,1,U) For(j,0,m) sum[i][j]=cst[i][j]=0;
}

int main() {
	read(Td); int x,y;
	while(Td--) {
		init(); clear();
		x=k+1; y=0; U=(1<<k+1)-1;
		For(i,1,U) sum[i][a[i]%m]=(ll)b[i];
		For(i,U+1,n) {
			if((i>>x)>1) x++,y=x%(k+1);
			sum[i>>(x-y)][a[i]%m]+=(ll)b[i];
		}
		For(i,0,m-1) For(j,0,m-1) v[i][j]=i<=j? j-i:j+m-i;
		For(i,1,U) For(j,0,m-1) For(k,0,m-1) 
			cst[i][j]+=sum[i][k]*v[k][j];
		For(i,1,U) For(j,0,m) dp[i][j]=INF;
		For(i,(1<<k),U) For(j,0,m-1) dp[i][j]=cst[i][j];
		Rep(i,(1<<k)-1,1) For(j,0,m-1) {
			For(t,0,m-1) {
				x=(j-t+m)%m;
				dp[i][j]=min(dp[i][j],cst[i][t]+dp[i<<1][x]+dp[i<<1|1][x]);
			}
		}
		printf("%lld\n",dp[1][0]);	
	}
	return 0;
}

  

posted @ 2018-05-25 15:52  shixinyi  阅读(626)  评论(0编辑  收藏  举报