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 }
View Code

 

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 }
View Code

 

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 }
View Code

 

posted @ 2018-05-24 21:16  啊宸  阅读(457)  评论(0编辑  收藏  举报