SDOI2018

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\n",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\n",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\n",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 }

原文地址:https://www.cnblogs.com/Achenchen/p/9077817.html

时间: 2024-08-30 15:51:35

SDOI2018的相关文章

bzoj 5329 [SDOI2018] 战略游戏

bzoj 5329 [SDOI2018] 战略游戏 Link Solution 很容易想到虚树 然后发现是一个图... 现学圆方树,套上去,做完了(模板题?) 就是直接上广义圆方树先把这玩意转换成一棵树,然后对当前询问建立虚树,断掉虚树里任何一个点都合法(包括不出现的点,指那些在某个点和其虚树上父亲之间的点),统计一下即可 Code // Copyright lzt #include<stdio.h> #include<cstring> #include<cstdlib>

[SDOI2018]战略游戏 圆方树,树链剖分

[SDOI2018]战略游戏 这题是道路相遇(题解)的升级版,询问的两个点变成了\(S\)个点. LG传送门 还是先建出圆方树,考虑对于询问的\(S\)个点,答案就是圆方树上能包含这些点的最小连通块中的圆点个数减去\(S\).问题变成了怎样求这样的连通块中的圆点个数,直接给结论吧:先搞出树的dfs序,把询问的点按dfs序从小到大排一遍序,每次把答案加上第\(i\)和第\(i + 1\)个点之间的圆点个数,但是不算lca,再加上第\(1\)个和第\(S\)个点之间的圆点个数,然后除以二就得到了这个

[SDOI2018]物理实验 set,扫描线,旋转坐标系

[SDOI2018]物理实验 set,扫描线,旋转坐标系 链接 loj 思路 先将导轨移到原点,然后旋转坐标系,参考博客. 然后分线段,每段的贡献(三角函数值)求出来,用自己喜欢的平衡树,我选set. 显然答案的一端是小线段的端点. 然后扫描线求出最大的ans. 代码 #include <bits/stdc++.h> using namespace std; const int N=1e5+7; int n,op[N]; long double X[N][2],Y[N][2],x[2],y[2

#LOJ2564 SDOI2018 原题识别 主席树

转载请注明原文地址:http://www.cnblogs.com/LadyLex/p/9057297.html 原题链接: 今天考试考了前天的SDOI考题 天啊我菜爆,只有T2拿了30分 然后考试后半程一直在打T1 觉得考试思路很有意思,于是就顺着打下来了 个人感觉这个是$O(nlogn^{2})$的,但是在loj上我比claris的程序快了1s多,只不过编程复杂度不止翻倍啊…… 下面介绍一下我的解法 其实最早启发我的是链上的部分分 定义$pre_{i}$为i前面最近的和i同色的点的下标,我们把

「SDOI2018」物理实验

题目大意: 这题不好描述,直接看原题吧…… 题解: 很无脑的题……就是卡精度+难写.代码能力还是太差了. 其实可以直接用long double肝过去.但我的代码似乎太丑了,以至于跑得奇慢无比. 代码: #include "bits/stdc++.h" using namespace std; inline int read() { int s=0,k=1;char ch=getchar(); while (ch<'0'|ch>'9') ch=='-'?k=-1:0,ch=g

SDOI2018:原题识别

题解: https://files.cnblogs.com/files/clrs97/old-solution.pdf Code: #include<cstdio> #include<cstdlib> #include<algorithm> using namespace std; typedef long long ll; const int N=100010,M=1010,E=5500000,BUF=10000000,OUT=10000000; unsigned i

Bzoj5332: [Sdoi2018]旧试题

国际惯例的题面首先我们进行一些相对显然的数学变化.解释一下第二行的那个变形,如果一个数是ijk的因数,那么它一定能被分解成三部分分别是i,j,k的因数.我们钦定一个质数只能在三部分的一个中出现.如果一个质数仅在ijk中的一个数中出现这样显然是对的,而在多个中出现的话,它贡献答案的次数为它出现的总次数+1次.而考虑把ijk的乘积分解质因数,然后考虑每个质数的贡献,会发现每个质数贡献答案的次数恰好为它的次数+1次,所以这样是对的.然后就是分析最后的这个公式了.右边的三个小求和号里的东西显然可以大力n

[bzoj5329][Sdoi2018]战略游戏

题目大意:多组数据,每组数据给一张图,多组询问,每个询问给一个点集,要求删除一个点,使得至少点集中的两个点互不连通,输出方案数 题解:圆方树,发现使得两个点不连通的方案数就是它们路径上的原点个数.如何处理重复?可以按圆方树的$dfn$序排序,相邻两点求一下贡献,这样贡献就被重复计算了两次,除去$k$个询问点就行了.还有每次计算中$lca$没有被统计,发现排序后第一个点和最后一个点的$lca$一定是深度最浅的,所以只有这个点没有被统计答案,加上即可 卡点:1.圆方树$dfn$数组没赋值 2.$LC

[SDOI2018]荣誉称号

题解: 并不需要什么算法 首先我们随便画一画就会发现 能画出一颗满二叉树 然后要满足每个点从上往下的路径和都相同(%m意义下) 一个点上可能对应了多个点 然后这样我们可以暴力dp $2^k*m^2+nm$的 应该过不了 我们注意到一个点本质不同的点只能有m个 所以对每个点开个数组记录一下为x的有几个 这样时间就是$2^k*m^2$的了 空间$2^k*m$ 原文地址:https://www.cnblogs.com/yinwuxiao/p/10044008.html