• [考试反思]0322省选模拟52:重现


    又是$dy$讲的原题,我要疯了。

    又成为了原题没$A$的人里的最高分(有个$P$用

    只记得时间复杂度,但是忘了具体怎么做。。。

    当时没听明白,后来也没时间回放研究,然后就挂了。

    怎么这么多原题啊啊啊啊啊

    幸亏$T2$送了不少分,最后没多少时间才打的$T1$,签到走人。

    这样,最后才勉强有了个三位数的得分。

    以后可能还是需要适度刚题。。。这暴力将近打满也没多少分。。。

    应该还是得$A$一个。不然绝对没好名次

    T1:图

    大意:无向联通图。求方案使(四色染色后边两点不同色)或(去掉一个奇环的所有边后图联通)。$n,m le 3 imes 10^5$

    图不会做那就生成树呗。

    生成树好啊,如果只考虑树边就能直接二色染色了。

    然而四色染色没见过啊。好象是两个二色染色的结合。

    对非树边能染出来就好了呀。染出来就行,染不出来就说明不是二分图,那就找个奇环。因为树边没被删所以一定联通。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define S 6666666
     4 int fir[S],l[S],to[S],FIR[S],L[S],TO[S],ec,EC,n,m,co[S],q[S],t,dep[S];
     5 void link(int a,int b){l[++ec]=fir[a];fir[a]=ec;to[ec]=b;}
     6 void con(int a,int b){link(a,b);link(b,a);}
     7 void Link(int a,int b){L[++EC]=FIR[a];FIR[a]=EC;TO[EC]=b;}
     8 void dfs(int p,int c,int fa=0){
     9     co[p]|=c;c^=1;
    10     for(int i=fir[p];i;i=l[i])if(!co[to[i]])dfs(to[i],c,p);
    11         else if(to[i]!=fa)Link(p,to[i]);
    12 }
    13 void DFS(int p,int c){
    14     co[p]|=c; q[++t]=p;
    15     for(int i=FIR[p];i;i=L[i])if(!(co[TO[i]]&8))DFS(TO[i],c^2);
    16         else if((co[TO[i]]^c)&2^2){
    17             printf("B ");
    18             int C=0;
    19             for(;q[C]!=TO[i];++C);
    20             printf("%d ",t-C+1);
    21             for(int i=C;i<=t;++i)printf("%d ",q[i]);
    22             exit(0);
    23         }
    24     t--;
    25 }
    26 int main(){
    27     cin>>n>>m;
    28     for(int i=1,x,y;i<=m;++i)scanf("%d%d",&x,&y),con(x,y);
    29     dfs(1,4);
    30     for(int i=1;i<=n;++i)if(!(co[i]&8))DFS(i,10);
    31     printf("A ");
    32     for(int i=1;i<=n;++i)printf("%d ",co[i]-11);
    33 }
    View Code

    T2:数列

    大意:交互。给定$a,b,n$。有$n$个$[0,10^a)$的数,称为数列$A$,你可以给出一个长为$n$的$[0,10^b)$数列$B$。

    交互库会回答$sumlimits_{i=1}^{n} A_i B_i$。最多调用$10$次询问后,输出$A$数列。

    $Subtask1:n=10,a=b$

    那么只需要每次让其中一个$B$为$1$其余均为$0$即可确定一个数。

    $Subtask2,3:n=25,a=2,b geq 5$

    那么只要手动哈希一下再哈希回来就行了。进制数$100$

    $Subtask4:n=16,a=57,b=50$

    还是哈希,但是因为位数不够,所以我们让最高的$8$位重叠,即两个数哈希一次,进制数$10^{49}$

    于是其中一个数的较低$49$位就确定了。一共需要$8$次询问。

    然后我们四对一组,以$10^8$为进制,把那些完全不确定的串再哈希一下。$2$次询问。

    这样我们就能确定第一对的较低$8$位的值,结合上面的结果可以得到另一个数较高的$8$位,再减法得出这一对数。

    然后在后面这个四对一组的哈希里删掉这一对继续做就行了。

    要写高精减。前导0的处理比较麻烦。

     1 #include<bits/stdc++.h>
     2 #include"s.hpp"
     3 using namespace std;
     4 int X[233],Y[233],Z[233];
     5 void rev(string&s){reverse(s.begin(),s.end());}
     6 void cpy(string s,int r,int b,int*a){
     7     for(int i=0;i<233;++i)a[i]=0;
     8     for(int i=0;i<r;++i)a[b+i]=s[i]-'0';
     9 }
    10 void dec(){
    11     for(int i=0;i<233;++i)Z[i]=0;
    12     for(int i=0;i<233;++i){Z[i]+=X[i]-Y[i];if(Z[i]<0)Z[i]+=10,Z[i+1]--;}
    13 }
    14 vector<string>guess(int n,int a,int b,int t){
    15     if(t==1){
    16         string A="1",B="0";
    17         vector<string>v(10),ans(10);
    18         for(int i=0;i<10;++i)v[i]=B;
    19         for(int i=0;i<10;++i)v[i]=A,ans[i]=prod(v),v[i]=B;
    20         return ans;
    21     }else if(2<=t&&t<=3){
    22         string _10000="10000",_100="100",_1="1",_0="0",zz="000000";
    23         vector<string>v(25),ans(25); string B;
    24         for(int i=0;i<n;++i)v[i]=_0;
    25         for(int i=0;i<8;++i){
    26             v[i*3]=_1,v[i*3+1]=_100,v[i*3+2]=_10000;
    27             string Q=prod(v);
    28             for(int j=0;j<6;++j)zz[j]='0';
    29             for(int j=0;j<Q.size();++j)zz[j]=Q[Q.size()-j-1];
    30             if(zz[5]!='0')ans[i*3+2]=B+zz[5]+zz[4];else ans[i*3+2]=zz[4];
    31             if(zz[3]!='0')ans[i*3+1]=B+zz[3]+zz[2];else ans[i*3+1]=zz[2];
    32             if(zz[1]!='0')ans[i*3+0]=B+zz[1]+zz[0];else ans[i*3+0]=zz[0];
    33             v[i*3]=_0,v[i*3+1]=_0,v[i*3+2]=_0;
    34         }
    35         v[24]="1";ans[24]=prod(v);
    36         for(int i=0;i<n;++i)cerr<<ans[i]<<endl;
    37         return ans;
    38     }else{
    39         string re[17],rt="10000000000000000000000000000000000000000000000000",b="1",_="00000000",T;
    40         vector<string>v(16),ans(16);
    41         for(int i=0;i<16;++i)v[i]="0";
    42         for(int i=0;i<16;i+=2){
    43             v[i]=rt;v[i|1]=b;
    44             re[i]=prod(v);rev(re[i]); while(re[i].size()<114)re[i]+='0';
    45             int pt=48; while(re[i][pt]=='0'&&pt)pt--;
    46             for(int j=0;j<=pt;++j)ans[i|1]+=re[i][j];
    47             v[i]=v[i|1]="0";
    48         }
    49         for(int Q=0;Q<16;Q+=8){
    50             v[Q]=b;v[Q+2]=b+_;v[Q+4]=v[Q+2]+_;v[Q+6]=v[Q+4]+_;
    51             T=prod(v); rev(T);
    52             for(int I=Q;I<Q+8;I+=2){
    53                 while(T.size()<66)T+='0';
    54                 cpy(re[I],re[I].size(),0,X); cpy(T,8,49,Y);    dec();
    55                 int pt=56;while(!Z[pt]&&pt)pt--;
    56                 if(pt)for(int i=49;i<=pt;++i)ans[I|1]+='0'+Z[i];
    57                 cpy(re[I],re[I].size(),0,X); cpy(ans[I|1],ans[I|1].size(),0,Y); dec();
    58                 pt=232;while(!Z[pt]&&pt)pt--;
    59                 if(pt)for(int i=49;i<=pt;++i)ans[I]+='0'+Z[i]; else ans[I]="0";
    60                 cpy(T,T.size(),0,X); cpy(ans[I],ans[I].size(),0,Y); dec(); 
    61                 T.clear(); pt=232;while(!Z[pt]&&pt)pt--;
    62                 if(pt)for(int i=8;i<=pt;++i)T+='0'+Z[i]; else T="0";
    63             }
    64             v[Q]=v[Q+2]=v[Q+4]=v[Q+6]="0";
    65         }
    66         for(int i=0;i<16;++i)rev(ans[i]);
    67         return ans;
    68     }
    69 }
    View Code

    T3:走路

    大意:数轴[1,n]每个整点有一家饭店,要从原点出发走回原点。每家饭店可选是否进去。只要进去就要吃$a_i$单位食物。

    如果目前为止一共吃了$A$单位食物则移动一单位距离消耗$A+1$体力。给定初始体力$x$,求最多能吃多少。$n le 10^5,x,a_i le 10^6$

    最优决策当然是回来的路上再吃。总代价是$2max(i)+sum a_i imes i$

    正着做不动,于是倒着来。设计$dp_{i,j}$表示$[i,n]$饭店一共吃$j$的最小代价。

    每次可以拿上述总代价的式子更新$dp$表示从哪里出发。

    或者$dp_{i,j+a[i]}=min(dp_{i+1,j}+a[i] imes i)$表示路上吃的。

    后一种转移,因为大于$i$的饭店每单位食物消耗都$geq i$所以第二维的枚举上届就是$frac{x}{i}$

    总时间复杂度是$O(x ln x)$

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int n,x,a[111111],dp[1111111];
     4 int main(){
     5     cin>>n>>x;
     6     for(int i=1;i<=n;++i)scanf("%d",&a[i]);
     7     for(int i=0;i<=x;++i)dp[i]=x+1;
     8     for(int i=n;i;--i){
     9         for(int j=x/i;j>=a[i];--j)dp[j]=min(dp[j-a[i]]+1ll*a[i]*i,1ll*dp[j]);
    10         dp[a[i]]=min(dp[a[i]]*1ll,(a[i]+2ll)*i);
    11     }for(int i=x;~i;--i)if(dp[i]<=x)return printf("%d
    ",i),0;
    12 }
    View Code
  • 相关阅读:
    hdu1087Super Jumping! Jumping! Jumping!(dp)
    划分树 hdu4417Super Mario
    poj2240Arbitrage(map+floyd)
    hdu4282A very hard mathematic problem
    hdu1421搬寝室(dp)
    【洛谷P3806】【模板】点分治1
    【CF914E】Palindromes in a Tree
    GDOI2020 游记
    【POJ2296】Map Labeler
    【洛谷P6623】树
  • 原文地址:https://www.cnblogs.com/hzoi-DeepinC/p/12547791.html
Copyright © 2020-2023  润新知