[考试反思]0324省选模拟54:缺失

来了一场既没有$c++11$也没有$O2$的考试。

然后喜闻乐见的出现了一些$CE$,以及被卡常的。

然而与我没有关系,$T1$想到了最高的一档暴力(正解被卡常除外)

然而里面用到了$map$,没$O2$跑的是真的慢,最后拿了个不高不低的$50pts$

然后$T2$是神仙题,$O(n^3)$的$dp$我是天生恐惧。就算改题也是尝试理解了好久。

然后牛一直说它简单,然而给我讲并没有听明白。

哭了,太菜了听啥都像嘲讽。他们不懂底层人民的生活。

虽说我到现在都不明白暴力为什么会挂。

$T3$的最高分$20$居然死信仰的$puts("0")$。数据真神奇,然后还有的人$5pts$思路挺神仙的。。

正解更神仙,完全想不到。

考后改题时间都砸$T2$上了,到处问问了两个半小时只有一个人给我讲,还没讲明白(不敢继续问了23333

后来发现$T1$比较简单就把$T1$弄了下来,然后继续到处问$T2$。很晚很晚才问明白然后$AC$

然后就没时间搞$T3$了。大概思想明白。可以看看$AK$神们的博客。

状态还是很差。快点调整回来啊!!!

T1:space

大意:四维空间,有四个排列$A,B,C,D$。$(i,j,k,l) \rightarrow (A_i,B_j,C_k,D_l)$的代价为$1$。其余代价为$2$。求最小代价的经过所有点的回路。$n \le 10^5$

排列交换当成建图貌似渐渐成为了套路。?

如果我们对四个维度所有点一起连边,那么最后的代价就是$n^4+$环的个数。

每个四维环都是由四个一维环拼接出来的。改变定义设$A_i$表示大小为$i$的环有多少个。

$ans=n^4+A_iB_jC_kD_l\frac{i,j,k,l}{lcm(i,j,k,l)}$

$A$的数量级别是$O(\sqrt{n})$的。所以总复杂度是$O(n^2logn)$的。

然后对前后两个一组分组,$meet  \ in \ middle$。

大概是个莫反。对于每种质因子考虑可以得到$\frac{abcd}{lcm(a,b,c,d)} = gcd(a,b)gcd(c,d)gcd(lcm(a,b),lcm(c,d))$

这样就可以把前后两部分分开。$(A_i,i,B_j,j) \rightarrow (A_iB_jgcd(i,j),lcm(i,j))$。得到新的二元组。

然后问题就在于二元组合并。懒得写公式了:

最后面的只与$Q$有关。可以预处理。我们对于每个$pair$把$second$分解质因数这样就能在合法的复杂度内求出$\varphi$和枚举约数。

然后就没了。但是因为没开$O2$所以$STL::map$超慢。手写哈希表是必要的(存$F$用)

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define S 211111
 4 #define mod 998244353
 5 int w[S],al[S],n,ans,A[S],B[S],C[S],D[S],a[S],b[S],c[S],d[S],X,Y,T[S];
 6 vector<int>_dv[S],_t[S];
 7 struct hashmap{
 8     #define $ 10000007
 9     int fir[$],l[$],to[$],v[$],ec;
10     int&operator[](int x){int r=x%$;
11         for(int i=fir[r];i;i=l[i])if(to[i]==x)return v[i];
12         l[++ec]=fir[r];fir[r]=ec;to[ec]=x;return v[ec];
13     }
14 }F;
15 int mo(int x){return x>=mod?x-mod:x;}
16 int gcd(int a,int b){return b?gcd(b,a%b):a;}
17 struct s{
18     int a; vector<int>b,t;
19     void init(int x,int y,int z,int w){
20         a=1ll*x*y*gcd(z,w)%mod;
21         for(int i=0;i<_dv[z].size();++i)T[_dv[z][i]]=max(T[_dv[z][i]],_t[z][i]);
22         for(int i=0;i<_dv[w].size();++i)T[_dv[w][i]]=max(T[_dv[w][i]],_t[w][i]);
23         for(int i=0;i<_dv[z].size();++i)b.push_back(_dv[z][i]), t.push_back(T[_dv[z][i]]),T[_dv[z][i]]=0;
24         for(int i=0;i<_dv[w].size();++i)if(T[_dv[w][i]])b.push_back(_dv[w][i]), t.push_back(T[_dv[w][i]]),T[_dv[w][i]]=0;
25     }
26 }x[S],y[S];
27 int read(){
28     register int p=0;register char ch=getchar();
29     while(!isdigit(ch))ch=getchar();
30     while(isdigit(ch))p=(p<<3)+(p<<1)+ch-48,ch=getchar();
31     return p;
32 }
33 void init(int*M,int*m){
34     for(int i=1;i<=n;++i)w[i]=read(),al[i]=0;
35     for(int i=1;i<=n;++i)if(!al[i]){
36         int p=i,c=1;al[p]=1;
37         while(!al[w[p]])p=w[p],al[p]=1,c++;
38         M[c]++;
39     }for(int i=1;i<=n;++i)if(M[i])m[++m[0]]=i;
40 }
41 void ctb(int o,int n,int w){
42     if(n==y[o].t.size()){F[w]=mo(F[w]+y[o].a);return;}
43     for(int j=0;j<=y[o].t[n];++j)ctb(o,n+1,w),w*=y[o].b[n];
44 }
45 int ask(int o,int n,int w,int phi,int ans=0){
46     if(n==x[o].t.size())return 1ll*F[w]*phi%mod;
47     for(int j=0;j<=x[o].t[n];++j)ans=mo(ans+ask(o,n+1,w,phi)),w*=x[o].b[n],phi=1ll*phi*(x[o].b[n]-(j?0:1));
48     return ans;
49 }
50 int main(){//freopen("space20.in","r",stdin);
51     cin>>n;init(A,a);init(B,b);init(C,c);init(D,d);
52     for(int i=2;i<=n;++i)if(_dv[i].empty())for(int j=i;j<=n;j+=i){
53         int x=j,c=0;_dv[j].push_back(i);
54         while(x%i==0)c++,x/=i; _t[j].push_back(c);
55     }
56     for(int i=1;i<=a[0];++i)for(int j=1;j<=b[0];++j)x[++X].init(A[a[i]],B[b[j]],a[i],b[j]);
57     for(int i=1;i<=c[0];++i)for(int j=1;j<=d[0];++j)y[++Y].init(C[c[i]],D[d[j]],c[i],d[j]);
58     for(int i=1;i<=Y;++i)ctb(i,0,1);
59     for(int i=1;i<=X;++i)ans=(ans+1ll*x[i].a*ask(i,0,1,1))%mod;
60     cout<<(ans+1ll*n*n%mod*n%mod*n)%mod<<endl;
61 }
View Code

T2:party

大意:树上有些点上有人,要求移动后形成一个联通块。(每点最多一个人)最小化总移动距离。$n \le 200$

神仙神仙神仙题。

设$dp[i][j]$表示,以$i$为根的子树中,不考虑$i$节点上的人,剩下在子树内形成了一个大小为$j$的联通块的最小代价。

默认剩下的$cnt-j$个人都围在$i$点上,且不考虑从$i$子树外到达$i$所用的步数。

那么在我们枚举一个根节点之后进行$dp$。考虑加入一个子树时会发生什么:

1)最后这个子树里一个人也没有。$dp[i][j]+=dp[son][0]+cnt[son]$。就是所有堆在$son$的人都上涌到$i$。因为不考虑从上面来的代价,所以只有$cnt[son]$有代价。

2)枚举这个子树里最后有多少人。$dp[i][j]=\min\limits_{k=1}^{j} (dp[i][j],dp[i][j-k]+dp[son][k]+ | k-sz[son] | )$

这里的绝对值非常妙。因为让外部走入和从内部走出的代价都是这个差值。

具体实现类似于一个背包。为了本层只更新本层,所以要倒着枚举$j$。

总的时间复杂度是$O(n^3)$的。

T3:wang

大意:要求设计值域定义域均为$Z$的函数$F$满足$F(2F(x)-x+1)=F(x)+C$。($C$为给定常数)。给定$n$对$(X,Y)$要求最小化$\sum\limits_{i=1}^{n} | F(X_i) - Y_i |$

时间不够。先鸽了。

猜你喜欢

转载自www.cnblogs.com/hzoi-DeepinC/p/12572014.html
今日推荐