CSPS模拟69-72

模拟69:

T1,稍数学,主要还是dp(转移莫名像背包???),当C开到n2时复杂度为n4,考场上想了半天优化结果发现n是100,n4可过

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 #define N 100050
 7 #define mod 1000000007
 8 using namespace std;
 9 int n,c;
10 long long m;
11 int inc[N],inv[N];
12 int dp[105][10005],f[2][105];
13 inline int qpow(int d,long long z)
14 {
15     int ret=1;
16     for(;z;z>>=1,d=1ll*d*d%mod)
17         if(z&1)ret=1ll*ret*d%mod;
18     return ret;
19 }
20 inline int C(int n,int m){return 1ll*inc[n]*inv[m]%mod*inv[n-m]%mod;}
21 void init(int n)
22 {
23     inc[0]=inv[0]=1;
24     for(int i=1;i<=n;++i)inc[i]=1ll*inc[i-1]*i%mod;
25     inv[n]=qpow(inc[n],mod-2);
26     for(int i=n-1;i;--i)inv[i]=1ll*inv[i+1]*(i+1)%mod;
27 }
28 int main()
29 {
30     cin>>n>>m>>c;init(n*n);
31     if(m==n){printf("%d
",C(n*n,c));return 0;}
32     long long t1=m/n,t2=m%n;
33     for(register int i=0;i<=n;++i)
34     {
35         f[0][i]=qpow(C(n,i),t1);
36         f[1][i]=1ll*f[0][i]*C(n,i)%mod;
37     }
38     dp[0][0]=1;
39     for(int i=1,z;i<=n;++i)
40     {
41         if(i<=t2)z=1;
42         else z=0;
43         for(int j=0;j<=n;++j)
44         {
45             for(int k=0;k+j<=c;++k)
46             {
47                 dp[i][k+j]+=1ll*dp[i-1][k]*f[z][j]%mod;
48                 if(dp[i][k+j]>=mod)dp[i][k+j]-=mod;
49             }
50         }
51     }
52     printf("%d
",dp[n][c]);
53     return 0;
54 }
View Code

T2:稍语文,考场上读错题,结果炸成0分。。。正解是单调栈,由于过于简单,直接粘代码

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define N 10000007
 6 using namespace std;
 7 const int inf=1000000007;
 8 int a[N],dp[N],n,ans=1;
 9 int pos[N],dq[N],mi[N],ba;
10 inline int read()
11 {
12     int s=0,b=0;char c=getchar();
13     while(c>'9'||c<'0')c=getchar();
14     while(c>='0'&&c<='9')s=s*10+c-'0',c=getchar();
15     return s;
16 }
17 int main()
18 {
19     n=read();if(!n){puts("0");return 0;}
20     for(register int i=1;i<=n;++i)a[i]=read(),mi[i]=a[i],pos[i]=i;
21     mi[0]=a[0]=inf;ba=1;pos[0]=0;
22     for(register int i=1;i<=n;++i)
23     {
24         while(a[i]>=a[dq[ba]])
25         {
26             ans=max(ans,i-pos[dq[ba]]+1);
27             if(mi[dq[ba]]<mi[dq[ba-1]]){
28                 mi[dq[ba-1]]=mi[dq[ba]];
29                 pos[dq[ba-1]]=pos[dq[ba]];
30             }
31             --ba;
32         }
33         if(a[i]>=mi[dq[ba]])
34         {
35             ans=max(ans,i-pos[dq[ba]]+1);
36         }
37         dq[++ba]=i;
38     }
39     printf("%d
",ans);
40     return 0;
41 }
View Code

T3:稍原题,回滚莫队。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 #define N 100050
 7 using namespace std;
 8 inline int read()
 9 {
10     int s=0,b=0;char c=getchar();
11     while(c>'9'||c<'0')c=getchar();
12     while(c>='0'&&c<='9')s=s*10+c-'0',c=getchar();
13     return s;
14 }
15 int a[N],n,m,sq,fl[N],fr[N],pd[N],al;
16 inline int Max(int a,int b){if(a>b)return a;return b;}
17 inline int Min(int a,int b){if(a>b)return b;return a;}
18 int ans[N];
19 struct node{
20     int l,r,id;
21     friend bool operator <(const node &a,const node &b)
22     {
23         if(a.l/sq==b.l/sq)return a.r<b.r;
24         return a.l<b.l;
25     }
26 }q[N];
27 void add(int x)
28 {
29     pd[x]=1;
30     if(pd[x-1])
31     {
32         fl[x]=fl[x-1];
33         fr[fl[x]]=x;
34         al=Max(al,x-fl[x]+1);
35     }
36     if(pd[x+1])
37     {
38         fr[x]=fr[x+1];
39         fl[fr[x]]=fl[x];
40         fr[fl[x]]=fr[x];
41         al=Max(al,fr[x]-fl[x]+1);
42     }
43     al=Max(al,fr[x]-fl[x]+1);
44 }
45 void del(int x)
46 {
47     if(pd[x+1])fl[fr[x]]=x+1;
48     if(pd[x-1])fr[fl[x]]=x-1;
49     fl[x]=fr[x]=x;pd[x]=0;
50 }
51 int main()
52 {
53 //    freopen("da.in","r",stdin);freopen("my.out","w",stdout);
54     n=read();m=read();
55     sq=sqrt(n);
56     for(int i=1;i<=n;++i)a[i]=read(),fl[i]=fr[i]=i;
57     for(int j=1;j<=m;++j)q[j].l=read(),q[j].r=read(),q[j].id=j;
58     sort(q+1,q+m+1);
59     int l=sq,r=sq,ks=sq;--r;
60     for(int i=1,lastal=0;i<=m;++i)
61     {
62 //        printf("i:%d tol:%d tor:%d
",i,q[i].l,q[i].r);
63         if(q[i].l/sq>q[i-1].l/sq)
64         {
65             for(int j=l;j<=r;++j)fl[a[j]]=fr[a[j]]=a[j],pd[a[j]]=0;
66             al=lastal=0;ks=l=r=(q[i].l/sq+1)*sq;--r;
67         }
68         if(q[i].l/sq==q[i].r/sq)
69         {
70             al=0;
71             for(int j=q[i].l;j<=q[i].r;++j)add(a[j]);
72             ans[q[i].id]=al;
73             for(int j=q[i].l;j<=q[i].r;++j)
74                 fl[a[j]]=fr[a[j]]=a[j],pd[a[j]]=0;
75             al=0;
76             continue;
77         }
78         //puts("yes");
79         while(r<q[i].r)add(a[++r]);
80 //        printf("al1:%d
",al);
81         lastal=al;
82         while(l>q[i].l)add(a[--l]);
83         ans[q[i].id]=al;
84 //        printf("al2:%d
",al);
85         while(l<ks)del(a[l++]);
86         al=lastal;
87     }
88     for(int i=1;i<=m;++i)
89         printf("%d
",ans[i]);
90     return 0;
91 }
View Code

模拟70:

T1:(由于此题已被各种方式*爆证明,直接粘)

 1 //数论,gcd,根号
 2 #include<iostream>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<algorithm>
 6 #include<cmath>
 7 using namespace std;
 8 long long n,ans;
 9 long long p[30],c[30];
10 int tot;
11 inline void fen(long long n)
12 {
13     tot=0;
14     for(register int i=2;i<=sqrt(n);++i)
15     {
16         if(n%i)continue;
17         p[++tot]=i;c[tot]=0;
18         while(n%i==0)++c[tot],n/=i;
19     }
20     if(n!=1)p[++tot]=n,c[tot]=1;
21     
22 }
23 inline void getans(long long al)
24 {
25     if(n/al>al)return;
26     if(n-al<al)return;
27     ans+=n/al-1;
28 }
29 void sear(int t,long long al)
30 {
31     if(t>tot){getans(al);return;}
32     const int m=(c[t]+1)/2;
33     for(int i=1;i<=m;++i)al*=p[t];
34         sear(t+1,al);
35 }
36 int main()
37 {
38 //    freopen("da.in","r",stdin);
39     while(1)
40     {
41         scanf("%lld",&n);
42         if(!n)return 0;
43         ans=0;fen(n);
44         sear(1,1ll);
45         ans*=8;
46         cout<<ans<<endl;
47     }
48 }
View Code

T2:(由于数据过水,暴力可过),正解复杂度带根号,用链表维护不同数的数量。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 #include<bitset>
 7 #define N 40050
 8 using namespace std;
 9 int n,m;
10 int dp[N],ans,a[N];
11 bitset<N>pd;
12 inline int Min(const int a,const int b){if(a<b)return a;return b;}
13 int pre[N],las[N],num[N],ne[N],tot,tp,pos[N];
14 struct node{int pre,ne,val,rk;}q[N];
15 void work2()
16 {
17     int al=0,ans=0;
18     for(int i=1;i<=n;++i)
19     {
20 //        printf("i:%d
",i);
21         dp[i]=dp[i-1]+1;
22         if(!pos[a[i]]){++tot;
23             q[tot].pre=tp;q[tot].rk=i;
24             q[tp].ne=tot;tp=tot;
25             pos[a[i]]=tot;
26         }
27         else
28         {
29             if(pos[a[i]]!=tp)
30             {
31                 int t=pos[a[i]],tl=q[t].pre,tr=q[t].ne;
32                 q[tl].ne=tr;q[tr].pre=tl;
33                 q[t].rk=i;q[tp].ne=t;q[t].pre=tp;tp=t;
34             }
35             else
36             {
37                 q[tp].rk=i;
38             }
39             for(int j=q[tp].pre,t=1;j;j=q[j].pre,++t)
40             {
41                 if(t*t>i)break;
42                 dp[i]=Min(dp[i],dp[q[j].rk]+t*t);
43             }
44         }
45     }
46     printf("%d
",dp[n]);
47 }
48 int main()
49 {
50     scanf("%d%d",&n,&m);ans=Min(n,m*m);
51     for(int i=1;i<=n;++i)scanf("%d",&a[i]);
52     pd.reset();work2();
53 }
View Code

T3:(由于出题人咕咕咕,咕掉了)已更

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<cmath>
  6 #define N 2000
  7 using namespace std;
  8 const int dx[8]={-3,0,3,0,-2,-2,2,2};
  9 const int dy[8]={0,-3,0,3,-2,2,-2,2};
 10 int n,ok,kkk;
 11 int tp,bt,le,ri,tox,toy,tag;
 12 int ans[N][N];
 13 int zt[7][7][7][7][7][7];
 14 inline int poss(int x){return (x-1)/5+1;}
 15 inline void getne(int x,int y)
 16 {
 17     if(poss(x)==1&&poss(y)!=1){tox=x;toy=y-3;tag=2;return;}
 18     if(poss(y)*5==n){tox=x-3;toy=y;tag=1;return;}
 19     if(poss(x)==2)
 20     {
 21         if(n==10){
 22             if(poss(y)&1){tox=x;toy=y+3;tag=4;return;}
 23             else{tox=x-3;toy=y;tag=1;return;}
 24         }
 25         
 26         if(poss(y)&1){tox=x+3;toy=y;tag=3;return;}
 27         else{
 28             if(poss(y)==n/5){tox=x-3;toy=1;tag=1;return;}
 29             else{tox=x;toy=y+3;tag=4;return;}
 30         }
 31     }
 32     if(poss(x)==n/5){
 33         if(poss(y)&1){tox=x;toy=y+3;tag=4;return;}
 34         else{tox=x-3;toy=y;tag=1;return;}
 35     }
 36     else{
 37         if(poss(y)&1){tox=x+3;toy=y;tag=3;return;}
 38         else{tox=x-3;toy=y;tag=1;return;}
 39     }
 40 }
 41 
 42 inline void getne2(int x,int y)
 43 {
 44     if(poss(x)==1&&poss(y)!=1){tox=x;toy=y-3;tag=2;return;}
 45     if(poss(y)==n/5||poss(y)==n/5-1)
 46     {
 47         if(poss(y)==n/5)
 48         {
 49             if(poss(x)&1){tox=x-3;toy=y;tag=1;return;}
 50             else{tox=x;toy=y-3;tag=2;return;}
 51         }
 52         else
 53         {
 54             if(poss(x)==2){tox=x-2;toy=y+2;tag=5;return;}
 55             if(poss(x)&1){tox=x;toy=y+3;tag=4;return;}
 56             else{tox=x-3;toy=y;tag=1;return;}
 57         }
 58     }
 59     if(poss(y)*5==n){tox=x-3;toy=y;tag=1;return;}
 60     if(poss(x)==2)
 61     {
 62         if(n==10){
 63             if(poss(y)&1){tox=x;toy=y+3;tag=4;return;}
 64             else{tox=x-3;toy=y;tag=1;return;}
 65         }
 66         
 67         if(poss(y)&1){tox=x+3;toy=y;tag=3;return;}
 68         else{
 69             if(poss(y)==n/5){tox=x-3;toy=1;tag=1;return;}
 70             else{tox=x;toy=y+3;tag=4;return;}
 71         }
 72     }
 73     if(poss(x)==n/5){
 74         if(poss(y)&1){tox=x;toy=y+3;tag=4;return;}
 75         else{tox=x-3;toy=y;tag=1;return;}
 76     }
 77     else{
 78         if(poss(y)&1){tox=x+3;toy=y;tag=3;return;}
 79         else{tox=x-3;toy=y;tag=1;return;}
 80     }
 81 }
 82 void sear(int x,int y,int al)
 83 {
 84     
 85     if(al==n*n-1)return;
 86     if(n&1)getne2(x,y);
 87     else getne(x,y);
 88 
 89     x=tox;y=toy;
 90     
 91     if(n&1)getne2(tox,toy);
 92     else getne(tox,toy);
 93     
 94     int bx,by;bx=poss(x)*5-4;by=poss(y)*5-4;
 95     switch(tag)
 96     {
 97         case 1:{tox=bx;toy=by+2;break;}
 98         case 2:{tox=bx+2;toy=by;break;}
 99         case 3:{tox=bx+4;toy=by+2;break;}
100         case 4:{tox=bx+2;toy=by+4;break;}
101         case 5:{tox=bx;toy=by+4;break;}
102     }
103     if(tox==x&&toy==y)--toy;
104     for(int i=bx;i<=bx+4;++i)
105         for(int j=by;j<=by+4;++j)
106             ans[i][j]=zt[x-bx+1][y-by+1][tox-bx+1][toy-by+1][i-bx+1][j-by+1]+al;
107     al+=25;
108     sear(tox,toy,al);
109 }
110 void dfs(int f1,int f2,int t1,int t2,int x,int y,int p)
111 {
112     zt[f1][f2][t1][t2][x][y]=p;
113     if(p==25){
114         if(x==t1&&y==t2){ok=1;return;}
115         zt[f1][f2][t1][t2][x][y]=0;
116         return;
117     
118     }
119     if(x==t1&&y==t2){
120         zt[f1][f2][t1][t2][x][y]=0;
121         return;
122     }
123     for(register int j=0;j<=7;++j)
124     {
125         if(x+dx[j]<=0||x+dx[j]>5||y+dy[j]<=0||y+dy[j]>5||zt[f1][f2][t1][t2][x+dx[j]][y+dy[j]])continue;
126         dfs(f1,f2,t1,t2,x+dx[j],y+dy[j],p+1);if(ok)return;
127     }
128     zt[f1][f2][t1][t2][x][y]=0;
129 }
130 void pr(int x,int y,int xx,int yy)
131 {
132     for(int i=1;i<=5;++i){
133         for(int j=1;j<=5;++j)
134             printf("%3d ",zt[x][y][xx][yy][i][j]);
135         puts("");
136     }
137 }
138 void prans()
139 {
140     for(int i=1;i<=n;++i){
141         for(int j=1;j<=n;++j)
142             printf("%3d ",ans[i][j]);
143         puts("");
144     }
145 }
146 int main()
147 {
148     cin>>n;kkk=5*5+1;
149     for(int i=1;i<=5;++i)
150         for(int j=1;j<=5;++j)
151             for(int k=1;k<=5;++k)
152                 for(int o=1;o<=5;++o)
153                     {if(k==i&&o==j)continue;ok=0;dfs(i,j,k,o,i,j,1);}
154     for(int i=1;i<=5;++i)
155         for(int j=1;j<=5;++j)
156             ans[i][j]=zt[1][1][3][3][i][j];
157     ans[3][3]=n*n;
158     if(n==5){prans();return 0;}
159     sear(5,5,24);prans();
160 }
View Code

模拟71

T1:正解为meet in the mid,但用乱搞加剪枝可过

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<cmath>
 6 #include<vector>
 7 using namespace std;
 8 const int mod=233337;
 9 const int N=(1<<20)+100;
10 struct hash_map{
11     int a[N],tot;
12     int he[mod];
13     int ne[N];
14     int val[N];
15     int to[N];
16     inline void add(int x,int t)
17     {
18         int k=x%mod;
19         to[++tot]=t;val[tot]=x;
20         ne[tot]=he[k];he[k]=tot;
21     }
22     int operator [](int x)
23     {
24         int k=x%mod;
25         for(int i=he[k];i;i=ne[i])
26             if(val[i]==x)return to[i];
27         return 0;
28     }
29 }h;
30 int n,tot,ans,b[N];
31 vector<int>v[N];
32 int bin[N];
33 int a[30];
34 inline int count(int x)
35 {
36     int ret=0;
37     for(int i=0;i<n;++i)
38         if(x&bin[i])++ret;
39     return ret;
40 }
41 int main()
42 {
43     scanf("%d",&n);for(int i=0;i<=n;++i)bin[i]=1<<i;
44     int p=0;
45     for(int i=0;i<n;++i)scanf("%d",&a[i]);
46     int gc=a[0];
47     for(int i=1;i<n;++i)gc=__gcd(gc,a[i]);
48     for(int j=0;j<n;++j)a[j]/=gc,p+=a[j];
49     p=(p+1)>>1;
50     const int ma=1<<n;
51     for(register int i=1,al,t;i<ma;++i)
52     {
53         al=0;
54         for(register int j=0;j<n;++j)
55             if(i&bin[j])al+=a[j];
56         b[i]=al;
57         if(al&1)
58         {
59             if(al<=p)
60             {
61                 if(!h[al])h.add(al,++tot);
62                 v[h[al]].push_back(i);
63             }
64             continue;
65         }
66         else
67         {
68             t=al>>1;
69             if(h[t])
70             {
71                 t=h[t];
72                 if(bin[count(i)]<v[t].size())
73                 {
74                     t=al>>1;
75                     for(register int j=i;j;j=(j-1)&i)
76                         if(b[j]==t){++ans;break;}
77                 }
78                 else
79                 {
80                     for(register int j=0;j<v[t].size();++j)
81                         if((v[t][j]&i)==v[t][j]){++ans;break;}
82                 }
83             }
84             if(al<=p)
85             {
86                 if(h[al]==0)h.add(al,++tot);
87                 v[h[al]].push_back(i);
88             }
89         }
90     }
91     cout<<ans<<endl;
92 }
View Code

打爆毛一琛轻轻松松

T2:我以前做过一个很SAO的题,叫做SAO,然后这题转化一下题意就和SAO很像,反正巨恶心,考场上凭借做过SAO拿到70。

关于SAO的blogs:https://www.cnblogs.com/loadingkkk/p/11220717.html

转化题意考虑一开始有一个1到n的序列,要把它通过一个1到n-1的序列转换成目标序列,考虑构造这个n-1的序列发现从目标序列一直跳(int i=n;i!=1;i=p[i])可以把顺序找出来

dp数组是定义在1~n-1的序列上的,然后dp[i][j]定义为考虑到序列上从i到n-1,i在构造的序列中的排名为j的方案数,dp时维护前缀和即可。

 1 #include<iostream>
 2 #include<cstdio>
 3 #define N 5050
 4 using namespace std;
 5 const int mod=1000000007;
 6 int n,a[N],ans,dp[N][N],pd[N];
 7 int main()
 8 {
 9     scanf("%d",&n);for(int i=1;i<=n;++i)scanf("%d",&a[i]),++a[i];
10     if(a[n]==n){puts("0");return 0;}
11     int pre=a[n];
12     for(int j=n;j>=1;--j)if(pre==j){pd[j]=1;pre=a[pre];}
13     dp[n-1][1]=1;
14     for(int i=n-2,al;i;--i){al=n-i-1;
15         if(pd[i+1])for(int o=1,tt=0;o<=al+1;++o){dp[i][o]=tt;tt+=dp[i+1][o];if(tt>=mod)tt-=mod;}
16         else for(int o=al,tt=0;o;--o){tt+=dp[i+1][o];if(tt>=mod)tt-=mod;dp[i][o]=tt;}
17     }
18     for(int i=1;i<=n-1;++i){ans+=dp[1][i];if(ans>=mod)ans-=mod;}
19     cout<<ans<<endl;
20 }
View Code

T3:这是一个复杂度和证明都很玄学的算法(......剪枝完暴力搜

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<map>
 6 #include<vector>
 7 #define N 10050
 8 using namespace std;
 9 int n,a[N],p,k,ans;
10 inline bool judge(const int x,const int ans)
11 {
12     const int mod=p;
13     register int ret=1,al=0;
14     for(register int i=1,to;i<=n;++i)
15     {
16         to=a[i]+x;if(to>=mod)to-=mod;
17         if(to>ans)return false;
18         if(al+to>ans){
19             al=0;++ret;
20             if(ret>k)return false;
21         }
22         al+=to;
23     }
24     return true;
25 }
26 void work(const int x)
27 {
28     int l=0,r=ans,mid;
29     while(l+1<r)
30     {
31         mid=l+r>>1;
32         if(judge(x,mid))r=mid;
33         else l=mid;
34     }
35     ans=r;
36 }
37 int main()
38 {
39     scanf("%d%d%d",&n,&p,&k);
40     for(int i=1;i<=n;++i)scanf("%d",&a[i]),ans+=a[i];
41     for(int i=0,ma;i<p;i+=p-ma)
42     {
43         if(judge(i,ans))work(i);
44         ma=0;
45         for(int j=1,to;j<=n;++j)
46         {
47             to=a[j]+i;if(to>=p)to-=p;
48             if(to>ma)ma=to;
49         }
50     }
51     cout<<ans<<endl;
52 }
View Code

模拟72:

T1:水,dp or 卡特兰

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 const int mod=1000000007;
 7 int n,m,dp[2050][2050][2],mu,al,ans;
 8 char s[100050];
 9 int main()
10 {
11     scanf("%d%d%s",&n,&m,s+1);
12     for(int i=1;i<=m;++i){
13         if(s[i]=='(')++al;
14         else
15         {
16             if(al)--al;
17             else ++mu;
18         }
19     }
20     if(mu>n-m||al>n-m){puts("0");return 0;}
21     if(n==m)
22     {
23         if(!mu&&!al){puts("1");return 0;}
24         else {puts("0");return 0;}
25     }
26     dp[0][0][0]=1;dp[1][1][0]=1;
27     if(!mu)
28     {
29         dp[1][al+1][1]=1;
30         if(al)dp[1][al-1][1]=1;
31     }
32     for(register int i=2;i<=n-m;++i)
33     {
34         dp[i][0][0]=dp[i-1][1][0];dp[i][0][1]=dp[i-1][1][1];
35         for(int j=1;j<=i;++j)
36         {
37             dp[i][j][0]=dp[i-1][j-1][0]+dp[i-1][j+1][0];
38             if(dp[i][j][0]>=mod)dp[i][j][0]-=mod;
39             dp[i][j][1]=dp[i-1][j-1][1]+dp[i-1][j+1][1];
40             if(dp[i][j][1]>=mod)dp[i][j][1]-=mod;
41         }
42         for(int j=i+1;j<=n-m;++j)
43         {
44             dp[i][j][1]=dp[i-1][j-1][1]+dp[i-1][j+1][1];
45             if(dp[i][j][1]>=mod)dp[i][j][1]-=mod;
46         }
47         for(int j=mu;j-mu+al<=n-m;++j)
48         {
49             dp[i][j-mu+al+1][1]+=dp[i-1][j][0];
50             if(dp[i][j-mu+al+1][1]>=mod)dp[i][j-mu+al+1][1]-=mod;
51             if(j-mu+al-1>=0)
52             {
53                 dp[i][j-mu+al-1][1]+=dp[i-1][j][0];
54                 if(dp[i][j-mu+al-1][1]>=mod)dp[i][j-mu+al-1][1]-=mod;
55             }
56         }
57     }
58     ans=dp[n-m][0][1];
59     if(!al)
60     {
61         ans+=dp[n-m][mu][0];
62         if(ans>=mod)ans-=mod;
63     }
64     cout<<ans<<endl;
65     return 0;
66 }
View Code

T2:主要在于dp状态设定,转移很简单

设dp[i][j][2][k]表示进行了i次操作,当前数二进制表示下后8位为j,第九位为0/1,第九位往前连续k位相同的概率

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<vector>
 6 #include<stack>
 7 #include<queue>
 8 #define N 5050
 9 using namespace std;
10 const double di=0.01;
11 int n,m,sta,t,cnt;
12 long long x;
13 double dp[205][1<<8][2][300];
14 double ans,p,q;
15 int bin[32];
16 int main()
17 {
18     for(int i=0;i<=30;++i)bin[i]=1<<i;
19     scanf("%lld%d%lf",&x,&n,&p);p*=0.01;q=1.0-p;
20     for(int i=0;i<8;++i)sta|=x&bin[i];
21     t=(x>>8)&1;cnt=1;
22     for(int i=9;i<=30;++i)
23     {
24         if(((x>>i)&1)==t)++cnt;
25         else break;
26     }
27     const int ma=1<<8;
28     dp[0][sta][t][cnt]=1;
29     for(int i=0;i<n;++i){
30         for(int j=0;j<ma;++j){
31             for(int k=1;k<=n+32;++k){
32                     if(j&bin[7])dp[i+1][(j<<1)^bin[8]][1][1]+=dp[i][j][0][k]*p;
33                     else dp[i+1][(j<<1)][0][k+1]+=dp[i][j][0][k]*p;
34                     if(j==255)dp[i+1][0][1][1]+=dp[i][j][0][k]*q;
35                     else dp[i+1][j+1][0][k]+=dp[i][j][0][k]*q;
36                     if(j&bin[7])dp[i+1][(j<<1)^bin[8]][1][k+1]+=dp[i][j][1][k]*p;
37                     else dp[i+1][(j<<1)][0][1]+=dp[i][j][1][k]*p;
38                     if(j==255)dp[i+1][0][0][k]+=dp[i][j][1][k]*q;
39                     else dp[i+1][j+1][1][k]+=dp[i][j][1][k]*q;
40             }
41         }
42     }
43     for(int j=1,d,x;j<ma;++j)
44     {
45         x=j;d=0;
46         while(!(x&1))x>>=1,++d;
47         for(int k=1;k<=n+32;++k)ans+=(dp[n][j][0][k]+dp[n][j][1][k])*d;
48     }
49     for(int k=1;k<=n+32;++k)
50     {
51         ans+=dp[n][0][1][k]*8;
52         ans+=dp[n][0][0][k]*(8+k);
53     }
54     printf("%.10lf
",ans);
55 }
View Code

T3:

先考虑连通图的情况。
首先如果原图不是二分图,显然无解。因为对于一个长度大于3的奇环,如果合并环上任意两个不相邻的点,一定会生成一个更小的奇环,最终会剩下一个三元环,无法继续合并。
对于任意联通的二分图,我们可以选定一个点s ,然后将所有与s距离相同的点合并。由于原图是二分图,所有与距离相同的点必然在同一侧,也就一定不相邻,这样就可以构造出一条链。因此只需要找出两个点,使得它们间的最短路径最长。显然这样构造是最优的。
考虑有多个连通分量的情况,我们对于每一个连通分量都构造了一条链,而对于任意两条链,我们显然可以通过一次合并操作将它们并成一条,长度为它们的长度之和。因此,答案就是所有连通块的直径之和。
使用 BFS 求出最短路,时间复杂度为n2

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<vector>
 6 #include<stack>
 7 #include<queue>
 8 #define N 5050
 9 using namespace std;
10 int n,m,ok=1;
11 int he[N],ne[500050],to[500050],tot;
12 void addedge(int x,int y){to[++tot]=y;ne[tot]=he[x];he[x]=tot;}
13 int f[N],ans[N];
14 int dfn[N],low[N],ys[N],cut[N],cnt,rt,kx,bl[N];
15 vector<int>scc[N];
16 stack<int>st;
17 //
18 int dis[1200][1200];
19 queue<int>q;
20 void dijiesitela(const int g)
21 {
22     dis[g][g]=1;int x,y;
23     q.push(g);
24     while(!q.empty())
25     {
26         x=q.front();q.pop();
27         for(int i=he[x];i;i=ne[i])
28         {
29             y=to[i];
30             if(dis[g][y])continue;
31             dis[g][y]=dis[g][x]+1;
32             q.push(y);
33         }
34     }
35 }
36 void tarjan(int g,int fa)
37 {
38     f[g]=rt;
39     for(int i=he[g],y;i;i=ne[i])
40     {
41         y=to[i];if(y==fa)continue;
42         if(ys[y]){if(ys[y]==ys[g]){ok=0;return;}}
43         else{ys[y]=ys[g]^1;tarjan(y,g);}
44     }
45 }
46 int main()
47 {
48     scanf("%d%d",&n,&m);
49     for(register int i=1,x,y;i<=m;++i)
50     {
51         scanf("%d%d",&x,&y);
52         addedge(x,y);addedge(y,x);
53     }
54     for(int i=1;i<=n;++i)
55         dijiesitela(i);
56     for(int i=1;i<=n;++i)
57         if(!f[i]){
58             ys[i]=2;rt=i;tarjan(i,0);
59             if(!ok){puts("-1");return 0;}
60         }
61     for(int i=1;i<=n;++i)
62         for(int j=1;j<=n;++j)
63             if(f[j]==f[i])ans[f[j]]=max(ans[f[j]],dis[i][j]-1);
64     int alans=0;
65     for(int i=1;i<=n;++i)alans+=ans[i];
66     cout<<alans<<endl;
67 }
View Code
原文地址:https://www.cnblogs.com/loadingkkk/p/11669482.html