• [考试反思]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) ightarrow (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_lfrac{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) ightarrow (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]=minlimits_{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)$要求最小化$sumlimits_{i=1}^{n} | F(X_i) - Y_i |$

    这个函数的奇怪性质肯定有好多要研究的地方。函数嵌套非常不爽,于是我们设$y=2F(x)-x+1$

    现在代回去好看一些:$F(y)=x+C$。

    两边同时$+C:F(y)+C=x+2C$

    然后等式左边就变成了原始式子右边的形式,推回到左边来得到:$F(2F(y)-y+1)=x+2C$

    把左边的$2F(y)$再代回$F(y)=F(x)+C$。剩余的$y$代回$y=2F(x)-x+1$

    然后惊喜的发现式子就只剩下了$F(x+2C)=F(x)+2C$

    这是个好性质。我们可以把括号内外的$2C$丢进来或撇出去。那么最简单的想法就是,在外部加上等量数后,内部可以对$2C$取模。

    也就是说,只要确定了$F(x)$的值,那么$F(x+2C),F(x+4C)...$就都确定了。

    所以说其实我们可以把$F(x)$表示为$t+nC$的形式。其中$0 le t < 2C$。至此还有两种表示方法,但是先往下看着。

    $F(2F(x)-x+1)=F(x)+C$

    可以代换了:$F(2t+2nC-x-1)=t+nC+C$

    然后上面已经说明$2C$可以提出,那么左边的$2nC$就可以拿出来了:$F(2t-x-1)+2nC=t+nC+C$

    也就是$F(2t-x+1)=t-nC+C$

    我们发现这时候在函数自变量里的$x$由正变为了负,我们把正的一项加回来,就能得到$F(x)+F(2t-x+1)=2t+C$

    换句话说,对于任意一对奇数偶数,若$a+b=2t+1,F(x)=t+nC$那么就有$F(a)+F(b)=2t+C$

    所以说,在$F(x)=t+nC(0 le t <2C)$的两种表达方式中,其中一种没什么用,而$t,x$奇偶性不同的那一种它有所限制。(当然两种表达形式都是成立的

    而我们又限定了$0 le t <2C$,也就是说,每个奇数一定对应某个特定偶数。某个偶数一定对应特定奇数。

    一旦$F(x)=t+nC$确定,那么$F(2t+1-x)$也就同时确定了。这也可见,对应关系是双向的,且每个数的度数均为一。

    于是我们就知道,$C$个奇数与$C$个偶数之间,存在完美匹配。这就是二分图匹配问题。

    回归原问题,我们要最小化纵坐标的差绝对值。我们所需要决定的只是配对关系,配对关系确定$t$也就确定了,然后$n$只要取该配对关系下的最优值即可。

    我们确定其中一个配对关系之后,那么这两个点的$F$值就同时确定了,模$2C$之后横坐标对应这两个点的代价也就确定了。

    所以说每种配对的贡献是可以分开计算的。我们现在来考虑某个配对$a,b$的代价。这就是我们配对时这条边的边权。

    沿用上面的定义,$a+b=2t+1$

    那么对于所有模$2C$后是偶数$a$的点$(X_i,Y_i)$,它贡献的代价是$| lfloor frac{X_i}{2C} floor imes 2C + F(a) -Y_i|$

    如果$F(a)=t+nC$那么就有$| lfloor frac{X_i}{2C} floor imes 2C + t+nC -Y_i|$

    同时$F(b)$也就确定了,是$2t+C - F(a) = t -nC + C$

    那么对于所有模$2C$后是偶数$a$的点$(X_i,Y_i)$,它贡献的代价是$| lfloor frac{X_i}{2C} floor imes 2C + F(b) -Y_i|$

    即为$| lfloor frac{X_i}{2C} floor imes 2C + t-nC+C -Y_i|$

    两种贡献中未知量只有$n$。我们把第二个式子的形式变一下:

    绝对值内取相反数结果不变,那么就是$| -  lfloor frac{X_i}{2C} floor imes 2C - t + nC  - C +Y_i|$

    这样,我们需要的就是一个合适的$n$值使两种贡献加起来尽量小。

    考虑另一个经典的问题模型:已知若干$x_i$,求一个$x$,最小化$sumlimits |x_i -x|$。答案是$x$是$x_i$的中位数

    在这里也只需要让$nC$尽量成为上述两种表达式对应的所有值的中位数即可。

    然后就只需要一个$MCMF$来进行最大权匹配了。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define S 66666
     4 int n,C,CC,_x,xa,xb,xp,_y,ya,yb,yp,fir[123],l[S],to[S],v[S],ec=1,q[S],iq[123];
     5 long long w[S],d[S],ans,f[S];
     6 void link(int a,int b,int V,long long W){l[++ec]=fir[a];fir[a]=ec;to[ec]=b;v[ec]=V;w[ec]=W;}
     7 void con(int a,int b,long long W){link(a,b,1,W);link(b,a,0,-W);}
     8 vector<int>X[123],Y[123];
     9 bool bfs(){
    10     memset(d,0x3f,sizeof d); memset(iq,0,sizeof iq); d[CC]=0; q[1]=CC;
    11     for(int h=1,t=1;h<=t;iq[q[h++]]=0)for(int i=fir[q[h]];i;i=l[i])if(v[i]&&d[to[i]]>d[q[h]]+w[i]){
    12         d[to[i]]=d[q[h]]+w[i]; if(!iq[to[i]])iq[q[++t]=to[i]]=1;
    13     }return d[CC+1]<1e17;
    14 }
    15 int dfs(int p,int f){int r=f;
    16     if(p==CC+1)return f; iq[p]=1;
    17     for(int i=fir[p];i&&r;i=l[i])if(v[i]&&d[to[i]]==d[p]+w[i]&&!iq[to[i]]){
    18         int x=dfs(to[i],1);
    19         if(!x)d[to[i]]=-1;
    20         else v[i]--,v[i^1]++,ans+=w[i],r--;
    21     }return f-r;
    22 }
    23 long long cal(int a,int b){
    24     int c=0,t=a+b>>1,nC1,nC2;long long f1=0,f2=0;
    25     for(int i=0;i<X[a].size();++i)f[++c]=-(X[a][i]/CC*CC+t-Y[a][i]);
    26     for(int i=0;i<X[b].size();++i)f[++c]=X[b][i]/CC*CC+t-Y[b][i]+C;
    27     sort(f+1,f+1+c);
    28     nC1=floor(f[c+1>>1]*1./C)*C;nC2=ceil(f[c+1>>1]*1./C)*C;
    29     for(int i=1;i<=c;++i)f1+=abs(f[i]-nC1),f2+=abs(f[i]-nC2);
    30     return min(f1,f2);
    31 }
    32 int main(){
    33     cin>>C>>n>>_x>>xa>>xb>>xp>>_y>>ya>>yb>>yp; CC=C+C;
    34     for(int i=0;i<n;++i)X[_x%CC].push_back(_x),Y[_x%CC].push_back(_y),_x=(1ll*_x*xa+xb)%xp,_y=(1ll*_y*ya+yb)%yp;
    35     for(int i=0;i<CC;i+=2)for(int j=1;j<CC;j+=2)con(i,j,cal(i,j));
    36     for(int i=0;i<CC;++i)if(i&1)con(i,CC+1,0);else con(CC,i,0);
    37     while(bfs())dfs(CC,C); cout<<ans;
    38 }
    View Code
  • 相关阅读:
    软件工程课程总结
    c++第五次作业
    软件工程第四次作业
    c++第四次作业
    软件工程第三次作业
    c++第三次作业
    软件工程基础第二次作业
    c++第二次作业
    c++第一次作业
    软件工程基础第一次作业
  • 原文地址:https://www.cnblogs.com/hzoi-DeepinC/p/12572014.html
Copyright © 2020-2023  润新知