题面:https://www.cnblogs.com/Juve/articles/11678524.html
骆驼:构造题,留坑
根据5×5的矩形构造成大矩形
毛一琛:
mid in the middle思想,先dfs一半,然后dfs后一半
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<unordered_map> 6 #include<set> 7 #define int long long 8 #define re register 9 using namespace std; 10 const int MAXN=23; 11 int n,m[MAXN],ans=0,tot=0; 12 unordered_map<int,int>mp; 13 set<int>s[1<<23]; 14 bool vis[1<<23]; 15 void DFS(re int now,re int num,re int st){ 16 if(now>n){ 17 if(mp.find(num)==mp.end()) return ; 18 int t=mp[num]; 19 for(set<int>::iterator it=s[t].begin();it!=s[t].end();++it){ 20 if(vis[(*it)|st]==0) ++ans; 21 vis[(*it)|st]=1; 22 } 23 return ; 24 } 25 DFS(now+1,num,st); 26 DFS(now+1,num+m[now],st|(1<<(now-1))); 27 DFS(now+1,num-m[now],st|(1<<(now-1))); 28 } 29 void dfs(re int now,re int num,re int st){ 30 if(now>n/2){ 31 int t; 32 if(mp.find(num)==mp.end()) t=mp[num]=++tot; 33 else t=mp[num]; 34 s[t].insert(st); 35 return ; 36 } 37 dfs(now+1,num,st); 38 dfs(now+1,num+m[now],st|(1<<(now-1))); 39 dfs(now+1,num-m[now],st|(1<<(now-1))); 40 } 41 signed main(){ 42 scanf("%lld",&n); 43 for(re int i=1;i<=n;++i) scanf("%lld",&m[i]); 44 vis[0]=1; 45 dfs(1,0,0);DFS(n/2+1,0,0); 46 printf("%lld ",ans); 47 return 0; 48 }
毛二琛:dp,不会
毛三琛:
二分思路考场上想到了,但是没有想到优化骗分
把x随机排个序,二分前先check一下是否比当先的ans优,不优就不二分
再加个clock
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define int long long 6 #define re register 7 using namespace std; 8 const int MAXN=1e4+5; 9 int n,k,p,a[MAXN],res,l=0x3f3f3f3f,r=0,ans=0,x[MAXN],b[MAXN]; 10 inline bool check(re int lim){ 11 re int tot=0,sum=0; 12 for(re int i=1;i<=n;++i){ 13 if(b[i]>lim) return 0; 14 if(sum+b[i]>lim){ 15 ++tot; 16 sum=b[i]; 17 if(tot>=k) return 0; 18 }else sum+=b[i]; 19 } 20 return 1; 21 } 22 signed main(){ 23 re double ck=clock(); 24 scanf("%lld%lld%lld",&n,&p,&k); 25 for(re int i=1;i<=n;++i){ 26 scanf("%lld",&a[i]); 27 r+=a[i],l=min(l,a[i]); 28 } 29 for(re int i=1;i<=p;++i) x[i]=i-1; 30 srand(time(0)); 31 random_shuffle(x+1,x+p+1); 32 ans=r; 33 for(re int i=1;i<=p;++i){ 34 if(clock()-ck>984000) break; 35 l=1,r=ans; 36 for(re int j=1;j<=n;++j){ 37 b[j]=(a[j]+x[i])%p; 38 l=max(l,b[j]); 39 } 40 if(!check(r)) continue; 41 while(l<r){ 42 re int mid=(l+r)>>1; 43 if(check(mid)) r=mid; 44 else l=mid+1; 45 } 46 ans=min(ans,l); 47 } 48 printf("%lld ",ans); 49 return 0; 50 }
简单的序列:
推式子,dp也可以
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define int long long 6 using namespace std; 7 const int MAXN=1e5+5,mod=1e9+7; 8 int n,m,tot=0,ans=0,cnt=0; 9 char s[MAXN]; 10 int max(int a,int b){ 11 return a>b?a:b; 12 } 13 int q_pow(int a,int b,int p){ 14 int res=1; 15 while(b){ 16 if(b&1) res=res*a%p; 17 a=a*a%p; 18 b>>=1; 19 } 20 return res; 21 } 22 int fac(int N){ 23 int res=1; 24 for(int i=2;i<=N;++i) res=res*i%mod; 25 return res%mod; 26 } 27 int C(int n,int m){ 28 if(m>n) return 0; 29 if(m==n) return 1; 30 return fac(n)*q_pow(fac(m)%mod,mod-2,mod)%mod*q_pow(fac(n-m)%mod,mod-2,mod)%mod; 31 } 32 int sta[MAXN],top=0; 33 signed main(){ 34 scanf("%lld%lld%s",&n,&m,s+1); 35 for(int i=1;i<=m;++i){ 36 if(s[i]=='(') sta[++top]=1; 37 else if(top) ++cnt,--top; 38 } 39 if(n&1){ 40 puts("0"); 41 return 0; 42 } 43 ans=C(n-m+1,n/2-m+cnt); 44 printf("%lld ",ans); 45 return 0; 46 }
简单的期望
dp[i][j][k][0/1]表示操作了i次,最后8位是j,右移8位后最后有连续k位是0/1。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define int long long 6 #define re register 7 using namespace std; 8 const int MAXN=205; 9 int x,n,pre[2005]; 10 double p,ans,f[MAXN][(1<<8)+5][235][2]; 11 signed main(){ 12 scanf("%lld%lld%lf",&x,&n,&p); 13 for(int i=1;i<=(1<<8);++i) pre[i*2]=pre[i]+1; 14 int d=x&1,b=x&255,c=0; 15 x>>=8;p/=100.0; 16 while(x&&(x&1)==d){ 17 x>>=1; 18 ++c; 19 } 20 f[0][b][c][d]=1.0; 21 for(int i=1;i<=n;++i){ 22 for(int j=0;j<(1<<8);++j){ 23 for(int k=0;k<=230;++k){ 24 if(j==((1<<8)-1)){ 25 f[i][0][k][0]+=f[i-1][j][k][1]*(1.0-p); 26 f[i][0][1][1]+=f[i-1][j][k][0]*(1.0-p); 27 }else{ 28 f[i][j+1][k][1]+=f[i-1][j][k][1]*(1.0-p); 29 f[i][j+1][k][0]+=f[i-1][j][k][0]*(1.0-p); 30 } 31 if(j>=(1<<7)){ 32 int b=(j<<1)&((1<<8)-1); 33 int tmp=((j<<1)&(1<<8))>>8; 34 if(tmp!=0){ 35 f[i][b][k+1][1]+=f[i-1][j][k][1]*p; 36 f[i][b][1][tmp]+=f[i-1][j][k][0]*p; 37 }else{ 38 f[i][b][1][tmp]+=f[i-1][j][k][1]*p; 39 f[i][b][k+1][0]+=f[i-1][j][k][0]*p; 40 } 41 }else{ 42 f[i][j<<1][1][0]+=f[i-1][j][k][1]*p; 43 f[i][j<<1][k+1][0]+=f[i-1][j][k][0]*p; 44 } 45 } 46 } 47 } 48 for(int j=1;j<=(1<<8);j++){ 49 for(int k=0;k<=230;k++) 50 ans+=pre[j]*(f[n][j][k][0]+f[n][j][k][1]); 51 } 52 for(int k=0;k<=230;k++) 53 ans+=((f[n][0][k][1]+f[n][0][k][0])*8)+f[n][0][k][0]*k; 54 printf("%0.6lf ",ans); 55 return 0; 56 }