SD的题有点反人类啊。。。
d1t1[SDOI2018]物理实验
感觉比较好想但不太好写,写了一半弃了
d1t2[SDOI2018]战略游戏
建出圆方树,每次建虚树,答案就是虚树上的原点个数减去询问的点数。
1 //Achen
2 #include<algorithm>
3 #include<iostream>
4 #include<cstring>
5 #include<cstdlib>
6 #include<vector>
7 #include<cstdio>
8 #include<queue>
9 #include<cmath>
10 #include<set>
11 #include<map>
12 #define For(i,a,b) for(int i=(a);i<=(b);i++)
13 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
14 const int N=4e5+7;
15 typedef long long LL;
16 typedef double db;
17 using namespace std;
18 int cas,n,m,Q,tot;
19
20 template<typename T> void read(T &x) {
21 char ch=getchar(); x=0; T f=1;
22 while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
23 if(ch=='-') f=-1,ch=getchar();
24 for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
25 }
26
27 struct graph {
28 int ecnt,fir[N],nxt[N],to[N],v[N],dfn[N],dfs_clock,f[N][20],R[N],sz[N];
29
30 void init() {
31 memset(fir,0,sizeof(fir));
32 memset(v,0,sizeof(v));
33 ecnt=0; For(i,1,n) v[i]=1;
34 }
35
36 int in(int y,int x) { return dfn[y]>=dfn[x]&&dfn[y]<dfn[x]+sz[x]; }
37
38 void add(int u,int v) {
39 nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v;
40 }
41
42 void dfs(int x,int fa) {
43 sz[x]=1;
44 f[x][0]=fa;
45 v[x]+=v[fa];
46 R[x]=R[fa]+1;
47 dfn[x]=++dfs_clock;
48 For(i,1,18) f[x][i]=f[f[x][i-1]][i-1];
49 for(int i=fir[x];i;i=nxt[i]) {
50 dfs(to[i],x);
51 sz[x]+=sz[to[i]];
52 }
53 }
54
55 int lca(int x,int y) {
56 if(R[x]<R[y]) swap(x,y);
57 Rep(i,18,0) if(R[f[x][i]]>=R[y])
58 x=f[x][i];
59 if(x==y) return x;
60 Rep(i,18,0) if(f[x][i]!=f[y][i])
61 x=f[x][i],y=f[y][i];
62 return f[x][0];
63 }
64
65 }G;
66
67 struct Tarjan {
68 int dfn[N],low[N],dfs_clock,rr,sta[N],top;
69 int ecnt,fir[N],nxt[N],to[N];
70
71 void init() {
72 memset(fir,0,sizeof(fir));
73 memset(dfn,0,sizeof(dfn));
74 ecnt=1; dfs_clock=0; top=0; tot=n;
75 }
76
77 void add(int u,int v) {
78 nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v;
79 nxt[++ecnt]=fir[v]; fir[v]=ecnt; to[ecnt]=u;
80 }
81
82 void tarjan(int x,int F) {
83 dfn[x]=low[x]=++dfs_clock;
84 for(int i=fir[x];i;i=nxt[i]) {
85 if(i==(F^1)) continue;
86 if(!dfn[to[i]]) {
87 sta[++top]=i;
88 tarjan(to[i],i);
89 if(low[to[i]]>=dfn[x]) {
90 G.add(x,++tot);
91 while(top) {
92 int j=sta[top--];
93 G.add(tot,to[j]);
94 if(j==i) break;
95 }
96 }
97 low[x]=min(low[x],low[to[i]]);
98 }
99 else low[x]=min(low[x],dfn[to[i]]);
100 }
101 }
102 }T;
103
104 bool cmp(const int &A,const int&B) { return G.dfn[A]<G.dfn[B]; }
105
106 struct work {
107 int q[N],sta[N],top;
108 void sol() {
109 read(n); read(m);
110 G.init(); T.init();
111 For(i,1,m) {
112 int u,v;
113 read(u); read(v);
114 T.add(u,v);
115 }
116 T.tarjan(1,0);
117 G.dfs(1,0);
118 read(Q);
119 while(Q--) {
120 int c; top=0;
121 read(c); q[0]=c;
122 For(i,1,c) read(q[i]);
123 sort(q+1,q+c+1,cmp);
124 For(i,1,c-1) q[++q[0]]=G.lca(q[i],q[i+1]);
125 sort(q+1,q+q[0]+1,cmp);
126 int sz=unique(q+1,q+q[0]+1)-(q+1);
127 int ans=q[1]<=n;
128 For(i,1,sz) {
129 while(top&&!G.in(q[i],q[sta[top]])) top--;
130 if(top) { ans+=G.v[q[i]]-G.v[q[sta[top]]]; }
131 sta[++top]=i;
132 }
133 printf("%d
",ans-c);
134 }
135 }
136 }W;
137
138 //#define DEBUG
139 int main() {
140 #ifdef DEBUG
141 freopen("1.in","r",stdin);
142 //freopen(".out","w",stdout);
143 #endif
144 read(cas);
145 while(cas--) W.sol();
146 return 0;
147 }
d1t3[SDOI2018]反回文串
我觉得有点神啊。。。
要用O(1)快速乘,不然会T成55分。
如果质因子的数组没开LL,会卡死在91分。。
如果抄了luogu题解里的O(1)快速乘,没有对结果取模,94分。。
1 //Achen
2 #include<algorithm>
3 #include<iostream>
4 #include<cstring>
5 #include<cstdlib>
6 #include<vector>
7 #include<cstdio>
8 #include<queue>
9 #include<cmath>
10 #include<set>
11 #include<map>
12 #define For(i,a,b) for(LL i=(a);i<=(b);i++)
13 #define Rep(i,a,b) for(LL i=(a);i>=(b);i--)
14 const int N=1e5+7;
15 typedef long long LL;
16 typedef long double LD;
17 typedef double db;
18 using namespace std;
19 LL T;
20 LL n,k,p,q[N],lq[N],cq[N];
21
22 template<typename T> void read(T &x) {
23 char ch=getchar(); x=0; T f=1;
24 while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
25 if(ch=='-') f=-1,ch=getchar();
26 for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
27 }
28
29 LL ksc(LL a,LL b,LL p) {
30 /*a%=p; b%=p;
31 LL rs=0,bs=a;
32 while(b) {
33 if(b&1) rs=(rs+bs)%p;
34 bs=(bs+bs)%p;
35 b>>=1;
36 }
37 return rs;*/
38 LL tp=a*b-(LL)((LD)a/p*b+1.0e-8)*p;
39 return tp<0?tp+p:tp%p;
40 }
41
42 LL tp=a*b-(LL)((LD)a/p*b+1.0e-8)*p;
43
44 LL ksm(LL a,LL b,LL p) {
45 LL rs=1,bs=a%p;
46 while(b) {
47 if(b&1) rs=ksc(rs,bs,p);
48 bs=ksc(bs,bs,p);
49 b>>=1;
50 }
51 return rs;
52 }
53
54 int miller_rabin(LL n) {
55 if(n==1||n==2||n==3||n==5||n==7||n==11) return 1;
56 if(!(n%2)||!(n%3)||!(n%5)||!(n%7)||!(n%11)) return 0;
57 LL u=n-1,k=0;
58 while(!(u&1)) { u>>=1; k++; }
59 For(ti,1,15) {
60 LL a=rand()%(n-2)+2;
61 LL x=ksm(a,u,n),y;
62 For(i,1,k) {
63 y=ksc(x,x,n);
64 if(y==1&&x!=1&&x!=n-1) return 0;
65 x=y;
66 }
67 if(x!=1) return 0;
68 }
69 return 1;
70 }
71
72 LL gcd(LL a,LL b) { return !b?a:gcd(b,a%b); }
73
74 LL pollard_rho(LL n,LL c) {
75 LL x=rand()%n,y=x;
76 for(LL i=2,k=2;;i++) {
77 x=(ksc(x,x,n)+c)%n;
78 LL tp=gcd(n,(x-y+n)%n);
79 if(tp>1&&tp<n) return tp;
80 if(x==y) return n;
81 if(i==k) k+=k,y=x;
82 }
83 }
84
85 void find(LL n) {
86 if(miller_rabin(n)) {
87 q[++q[0]]=n;
88 return ;
89 }
90 LL tp=n;
91 for(LL c=13;;c++) {
92 tp=pollard_rho(n,c);
93 if(tp>1&&tp<n) break;
94 }
95 find(tp); find(n/tp);
96 }
97
98 LL F(LL d) { return ksm(k,((d&1)?d/2+1:d/2),p); }
99 LL h(LL d) { return (d&1)?d%p:d/2%p; }
100
101 LL ans;
102 void dfs(int pos,int up,LL now,LL tt) {
103 if(pos==up+1) {
104 LL d=n/now;
105 if((d&1)&&!(now&1)) ;
106 else ans=(ans+F(d)*h(d)%p*tt%p)%p; return;
107 }
108 For(i,0,cq[pos]) {
109 dfs(pos+1,up,now,i?(1-lq[pos]%p+p)%p*tt%p:tt);
110 now*=lq[pos];
111 }
112 }
113
114 void solve() {
115 sort(q+1,q+q[0]+1); lq[0]=0;
116 For(i,1,q[0]) {
117 if(i==1||q[i]!=q[i-1]) { lq[++lq[0]]=q[i]; cq[lq[0]]=1; }
118 else cq[lq[0]]++;
119 }
120 ans=0; dfs(1,lq[0],1,1);
121 printf("%lld
",ans);
122 }
123
124 //#define DEBUG
125 int main() {
126 #ifdef DEBUG
127 freopen("1.in","r",stdin);
128 //freopen(".out","w",stdout);
129 #endif
130 srand(998244353);
131 read(T);
132 while(T--) {
133 read(n); read(k); read(p);
134 q[0]=0; find(n);
135 solve();
136 }
137 return 0;
138 }
d2t1[SDOI2018]原题识别
什么神题啊。。。
感觉前30分可以树上莫队,中间30分可以树套树搞一下。
正解好神啊,不会啊,等我什么时候学会了来补吧。
d2t2[SDOI2018]旧试题
题解超详细的。
也好神啊。
听说很卡常,大常数选手不敢写。。
d2t3[SDOI2018]荣誉称号
全场最简单的一道题。
转化为二叉树,限制变成树上任意一条长度为k+1的链的和mod m==0
发现要满足要求,则i*2^(k+1)和i在mod m意义下同余。
于是可以拿前2^k-1个点dp,在每个点处计算它和它下面和它同余的所有点的代价和。
这个代价可以算出第一个然后预处理出b的前缀和来快速转移。
然后就可以2^k*m^2的dp转移了。
1 //Achen
2 #include<algorithm>
3 #include<iostream>
4 #include<cstring>
5 #include<cstdlib>
6 #include<vector>
7 #include<cstdio>
8 #include<queue>
9 #include<cmath>
10 #include<set>
11 #include<map>
12 #define For(i,a,b) for(int i=(a);i<=(b);i++)
13 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
14 const int N=2e7+7;
15 typedef long long LL;
16 typedef double db;
17 using namespace std;
18 int T,n,k,m,a[N],b[N],sta[N],top;
19
20 template<typename T> void read(T &x) {
21 char ch=getchar(); x=0; T f=1;
22 while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
23 if(ch=='-') f=-1,ch=getchar();
24 for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
25 }
26
27 unsigned int SA, SB, SC;int p, A, B;
28 unsigned int rng61(){
29 SA ^= SA << 16;
30 SA ^= SA >> 5;
31 SA ^= SA << 1;
32 unsigned int t = SA;
33 SA = SB;
34 SB = SC;
35 SC ^= t ^ SA;
36 return SC;
37 }
38 void gen(){
39 scanf("%d%d%d%d%u%u%u%d%d", &n, &k, &m, &p, &SA, &SB, &SC, &A, &B);
40 for(int i = 1; i <= p; i++)scanf("%d%d", &a[i], &b[i]);
41 for(int i = p + 1; i <= n; i++){
42 a[i] = rng61() % A + 1;
43 b[i] = rng61() % B + 1;
44 }
45 }
46
47 bool cmp(const int &A,const int &B) {
48 return a[A]<a[B];
49 }
50
51 LL dp[4149][207],t[207],c[207];
52 void solve() {
53 LL ans=0;
54 For(i,1,n) a[i]%=m;
55 memset(dp,127,sizeof(dp));
56 Rep(i,(1<<k+1)-1,1) {
57 memset(t,0,sizeof(t));
58 memset(c,0,sizeof(c));
59 top=0;
60 for(LL pos=i,bs=1;pos<=n;pos*=(1<<k+1),bs*=(1<<k+1)) {
61 for(int l=pos;l/bs==i;l++) {
62 sta[++top]=l; c[a[l]]+=b[l];
63 }
64 }
65 For(j,0,m-1) c[j]+=c[j-1];
66 For(j,0,m-1) {
67 if(j==0) For(k,1,top) t[j]+=(a[sta[k]]<=j?j-a[sta[k]]:m-(a[sta[k]]-j))*b[sta[k]];
68 else t[j]=t[j-1]+c[j-1]-(m-1)*(c[j]-c[j-1])+(c[m-1]-c[j]);
69 }
70 if(i>=(1<<k)) {
71 For(j,0,m-1) dp[i][j]=t[j];
72 }
73 else {
74 For(j,0,m-1) For(k,0,m-1) {
75 LL tp=dp[i<<1][j]+dp[(i<<1)|1][j];
76 dp[i][(j+k)%m]=min(dp[i][(j+k)%m],tp+t[k]);
77 }
78 }
79 }
80 printf("%lld
",dp[1][0]);
81 }
82
83 //#define DEBUG
84 int main() {
85 #ifdef DEBUG
86 freopen("1.in","r",stdin);
87 //freopen(".out","w",stdout);
88 #endif
89 read(T);
90 while(T--) {
91 gen();
92 solve();
93 }
94 return 0;
95 }