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;
}
弱者就是会被欺负呀

浙公网安备 33010602011771号