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\n",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\n",dp[n][c]); 53 return 0; 54 }
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\n",ans); 40 return 0; 41 }
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\n",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\n",al); 81 lastal=al; 82 while(l>q[i].l)add(a[--l]); 83 ans[q[i].id]=al; 84 // printf("al2:%d\n",al); 85 while(l<ks)del(a[l++]); 86 al=lastal; 87 } 88 for(int i=1;i<=m;++i) 89 printf("%d\n",ans[i]); 90 return 0; 91 }
模拟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 }
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\n",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\n",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 }
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 }
模拟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 }
打爆毛一琛轻轻松松
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 }
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 }
模拟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 }
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\n",ans); 55 }
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 }