题面:https://www.cnblogs.com/Juve/articles/11752338.html https://www.cnblogs.com/Juve/articles/11752414.html
最近咕的稍多,就简单写一下题解了(其实也不算题解),反正就是一句话,而且都是这几套题改完的
模拟87:
maze:
在实数上二分,跑最短路check,spfa比dij快多l
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 #include<cmath> 7 #define int long long 8 using namespace std; 9 const int MAXN=105; 10 int n,m,sx,sy,tx,ty; 11 int dx[4]={0,0,1,-1}; 12 int dy[4]={1,-1,0,0}; 13 bool mp[MAXN][MAXN],vis[MAXN*MAXN]; 14 double s,dis[MAXN*MAXN],l,r,ans; 15 int calc(int x,int y){ 16 return (x-1)*m+y; 17 } 18 queue< pair<int,int> >qu; 19 double spfa(int x,int y,double k){ 20 for(int i=1;i<=n;++i) 21 for(int j=1;j<=m;++j) dis[calc(i,j)]=1e11; 22 //printf("%0.0lf ",dis[1]); 23 memset(vis,0,sizeof(vis)); 24 int st=calc(x,y); 25 dis[st]=0.0; 26 qu.push(make_pair(x,y)); 27 vis[st]=1; 28 while(!qu.empty()){ 29 pair<int,int>p=qu.front(); 30 qu.pop(); 31 int xx=p.first,yy=p.second; 32 st=calc(xx,yy); 33 for(int i=0;i<4;++i){ 34 int a=xx+dx[i],b=yy+dy[i]; 35 if(mp[a][b]==1||a<1||b<1||a>n||b>m) continue; 36 int c=calc(a,b); 37 if(i<2){ 38 if(dis[c]>dis[st]+1.0){ 39 dis[c]=dis[st]+1.0; 40 if(!vis[c]) qu.push(make_pair(a,b)); 41 } 42 }else{ 43 if(dis[c]>dis[st]+k){ 44 dis[c]=dis[st]+k; 45 if(!vis[c]) qu.push(make_pair(a,b)); 46 } 47 } 48 } 49 vis[st]=0; 50 } 51 return dis[calc(tx,ty)]; 52 } 53 priority_queue< pair<double, pair<int,int> > > q; 54 double dijkstra(int x,int y,double k){ 55 for(int i=1;i<=n;++i) 56 for(int j=1;j<=m;++j) dis[calc(i,j)]=1e11; 57 //printf("%0.0lf ",dis[1]); 58 memset(vis,0,sizeof(vis)); 59 int st=calc(x,y); 60 dis[st]=0.0; 61 q.push(make_pair(0.0,make_pair(x,y))); 62 while(!q.empty()){ 63 pair<int,int>p=q.top().second; 64 q.pop(); 65 int xx=p.first,yy=p.second; 66 st=calc(xx,yy); 67 if(vis[st]) continue; 68 vis[st]=1; 69 for(int i=0;i<4;++i){ 70 int a=xx+dx[i],b=yy+dy[i]; 71 if(mp[a][b]==1||a<1||b<1||a>n||b>m) continue; 72 int c=calc(a,b); 73 if(i<2){ 74 if(dis[c]>dis[st]+1.0){ 75 dis[c]=dis[st]+1.0; 76 q.push(make_pair(-dis[c],make_pair(a,b))); 77 } 78 }else{ 79 if(dis[c]>dis[st]+k){ 80 dis[c]=dis[st]+k; 81 q.push(make_pair(-dis[c],make_pair(a,b))); 82 } 83 } 84 } 85 } 86 //cout<<calc(tx,ty)<<' '<<dis[calc(tx,ty)]<<endl; 87 return dis[calc(tx,ty)]; 88 } 89 signed main(){ 90 //freopen("test.in","r",stdin); 91 scanf("%lld%lld",&n,&m); 92 scanf("%lld%lld%lld%lld",&sx,&sy,&tx,&ty); 93 for(int i=1;i<=n;++i){ 94 for(int j=1,x;j<=m;++j){ 95 scanf("%lld",&x); 96 mp[i][j]=x; 97 } 98 } 99 scanf("%lf",&s); 100 l=0,r=s; 101 while(fabs(r-l)>1e-5){ 102 double mid=(r+l)/2.0; 103 if(dijkstra(sx,sy,mid)<=s) ans=mid,l=mid; 104 else r=mid; 105 } 106 printf("%0.3lf ",ans); 107 return 0; 108 }
bird:
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=5e5+5; 8 int n,k,tot=0,f[MAXN],maxx=0,ans=0; 9 struct node{ 10 int l,r; 11 friend bool operator < (node p,node q){ 12 return p.r==q.r?p.l<q.l:p.r<q.r; 13 } 14 }b[MAXN]; 15 int c[MAXN],num[MAXN],d[MAXN],in[MAXN]; 16 int max(int a,int b){ 17 return a>b?a:b; 18 } 19 int tr[MAXN<<2],laz[MAXN<<2]; 20 void down(int k){ 21 tr[k<<1]+=laz[k],tr[k<<1|1]+=laz[k]; 22 laz[k<<1]+=laz[k],laz[k<<1|1]+=laz[k]; 23 laz[k]=0; 24 } 25 void update(int k,int l,int r,int pos,int val){ 26 if(l==r){ 27 tr[k]=val; 28 return ; 29 } 30 if(laz[k]) down(k); 31 int mid=(l+r)>>1; 32 if(pos<=mid) update(k<<1,l,mid,pos,val); 33 else update(k<<1|1,mid+1,r,pos,val); 34 tr[k]=max(tr[k<<1],tr[k<<1|1]); 35 } 36 void update(int k,int l,int r,int opl,int opr,int val){ 37 if(opl<=l&&r<=opr){ 38 tr[k]+=val,laz[k]+=val; 39 return ; 40 } 41 if(laz[k]) down(k); 42 int mid=(l+r)>>1; 43 if(opl<=mid) update(k<<1,l,mid,opl,opr,val); 44 if(opr>mid) update(k<<1|1,mid+1,r,opl,opr,val); 45 tr[k]=max(tr[k<<1],tr[k<<1|1]); 46 } 47 int query(int k,int l,int r,int opl,int opr){ 48 if(opl<=l&&r<=opr) return tr[k]; 49 if(laz[k]) down(k); 50 int mid=(l+r)>>1,res=0; 51 if(opl<=mid) res=max(res,query(k<<1,l,mid,opl,opr)); 52 if(opr>mid) res=max(res,query(k<<1|1,mid+1,r,opl,opr)); 53 return res; 54 } 55 signed main(){ 56 scanf("%lld%lld",&n,&k); 57 for(int i=1,l,r;i<=n;++i){ 58 scanf("%lld%lld",&l,&r); 59 if(r<0) continue; 60 l=max(0,l);++l,++r; 61 b[++tot]=(node){l,r}; 62 ++d[l],--d[r+1],++in[l]; 63 maxx=max(maxx,r+1); 64 } 65 sort(b+1,b+tot+1); 66 for(int i=1;i<=maxx;++i) d[i]+=d[i-1]; 67 int now=0,p=1; 68 for(int i=1;i<=maxx;++i){ 69 f[i]=d[i]+query(1,0,maxx,max(0,i-2*k),max(0,i-k)); 70 ans=max(f[i],ans); 71 now+=in[i]; 72 update(1,0,maxx,i,f[i]-now); 73 while(p<=tot&&b[p].r==i){ 74 --now; 75 update(1,0,maxx,b[p].l,b[p].r,1); 76 ++p; 77 } 78 } 79 printf("%lld ",ans); 80 return 0; 81 }
stone:
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=1e6+5; 8 int n,m,ans=0,l[MAXN],r[MAXN],sum[3][3][MAXN]; 9 char s1[MAXN],s2[MAXN]; 10 signed main(){ 11 scanf("%s%s",s1+1,s2+1); 12 n=strlen(s1+1),m=strlen(s2+1); 13 int p=1; 14 for(int i=1;i<=n;++i){ 15 l[i]=p; 16 if(s1[i]==s2[p]) ++p; 17 } 18 p=1; 19 for(int i=1;i<=m;++i){ 20 if(s2[i]==s1[p]) ++p; 21 r[p]=min(i+1,m); 22 } 23 if(r[1]==0) r[1]=1; 24 for(int i=1;i<=n;++i){ 25 if(!r[i]) r[i]=m; 26 ans+=r[i]-l[i]+1; 27 } 28 for(int i=2;i<=m;++i){ 29 for(int k1=0;k1<3;++k1) 30 for(int k2=0;k2<3;++k2){ 31 sum[k1][k2][i]=sum[k1][k2][i-1]; 32 } 33 ++sum[s2[i]-'A'][s2[i-1]-'A'][i]; 34 } 35 for(int i=2;i<=n;++i){ 36 if(s1[i-1]!=s1[i]) 37 ans-=sum[s1[i-1]-'A'][s1[i]-'A'][r[i]]-sum[s1[i-1]-'A'][s1[i]-'A'][l[i]-1]; 38 //cout<<i<<' '<<ans<<' '<<s1[i-1]-'A'<<' '<<s1[i]-'A'<<endl; 39 } 40 printf("%lld ",ans); 41 return 0; 42 }
模拟88:
军训队列:
排序一定不会更劣,
设f[i][j]表示前i个分了j个队列的最小值,则有方程:$f[i][j]=min(f[p][j-1]+(a[i]-a[p])^2),pin[1,i]$
然后我们发现值域很小,unique后就能过了,当然也可以斜率优化
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; 8 int n,k; 9 double a[MAXN],f[MAXN][25],ans; 10 signed main(){ 11 scanf("%lld%lld",&n,&k); 12 memset(f,127,sizeof(f)); 13 for(int i=1;i<=n;++i){ 14 scanf("%lf",&a[i]); 15 } 16 f[0][0]=0; 17 sort(a+1,a+n+1); 18 n=unique(a+1,a+n+1)-a-1; 19 for(int i=1;i<=n;++i){ 20 for(int j=1;j<=min(i,k);++j) 21 for(int p=1;p<=i;++p){ 22 f[i][j]=min(f[i][j],f[p-1][j-1]+(a[i]-a[p])*(a[i]-a[p])); 23 } 24 } 25 printf("%0.2lf ",f[n][min(n,k)]); 26 return 0; 27 }
山屋惊魂:模拟+概率
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 double res[10][20],f[102][10][10][10][10],ans[4][9],dead; 7 char ch[12]; 8 int p[4],ww[4][9],n; 9 int cal(){ 10 if(ch[1]=='M') return 0; 11 else if(ch[2]=='p') return 1; 12 else if(ch[2]=='a') return 2; 13 else return 3; 14 } 15 int calc(){ 16 int len=strlen(ch+1); 17 if(len==2){ 18 if(ch[1]=='>') return 4; 19 else return 2; 20 }else{ 21 if(ch[1]=='<') return 1; 22 else return 3; 23 } 24 } 25 void work1(int tim,int pos,int val){ 26 for(int i=1;i<=8;++i){ 27 for(int j=1;j<=8;++j){ 28 for(int p=1;p<=8;++p){ 29 for(int q=1,now;q<=8;++q){ 30 if(pos==0){ 31 if(i+val<=0) continue; 32 now=min(8,i+val); 33 f[tim][now][j][p][q]+=f[tim-1][i][j][p][q]; 34 }else if(pos==1){ 35 if(j+val<=0) continue; 36 int now=min(8,j+val); 37 f[tim][i][now][p][q]+=f[tim-1][i][j][p][q]; 38 }else if(pos==2){ 39 if(p+val<=0) continue; 40 now=min(8,p+val); 41 f[tim][i][j][now][q]+=f[tim-1][i][j][p][q]; 42 }else{ 43 if(q+val<=0) continue; 44 now=min(8,q+val); 45 f[tim][i][j][p][now]+=f[tim-1][i][j][p][q]; 46 } 47 } 48 } 49 } 50 } 51 } 52 void work2(int tim,int pos,int flag,int val){ 53 for(int i=1;i<=8;++i){ 54 for(int j=1;j<=8;++j){ 55 for(int p=1;p<=8;++p){ 56 for(int q=1,now;q<=8;++q){ 57 for(int k=0;k<=2*val;++k){ 58 if(pos==0){ 59 if(i+flag*k<=0) continue; 60 now=min(8,i+flag*k); 61 f[tim][now][j][p][q]+=f[tim-1][i][j][p][q]*res[val][k]; 62 }else if(pos==1){ 63 if(j+flag*k<=0) continue; 64 int now=min(8,j+flag*k); 65 f[tim][i][now][p][q]+=f[tim-1][i][j][p][q]*res[val][k]; 66 }else if(pos==2){ 67 if(p+flag*k<=0) continue; 68 now=min(8,p+flag*k); 69 f[tim][i][j][now][q]+=f[tim-1][i][j][p][q]*res[val][k]; 70 }else{ 71 if(q+flag*k<=0) continue; 72 now=min(8,q+flag*k); 73 f[tim][i][j][p][now]+=f[tim-1][i][j][p][q]*res[val][k]; 74 } 75 } 76 } 77 } 78 } 79 } 80 } 81 void work3(int tim,int pos1,int fh,int lim,int pos2,int flag,int val){//第几次,用pos1判定,符号,判定的数,给谁改变,加还是减,加或减多少 82 val*=flag; 83 for(int i=1;i<=8;++i){ 84 for(int j=1;j<=8;++j){ 85 for(int p=1;p<=8;++p){ 86 for(int q=1;q<=8;++q){ 87 double ban=0.0; 88 for(int k=0;k<=16;++k){ 89 if(fh==1){//< 90 if(pos1==0) ban+=(k<lim)*res[ww[0][i]][k]; 91 else if(pos1==1) ban+=(k<lim)*res[ww[1][j]][k]; 92 else if(pos1==2) ban+=(k<lim)*res[ww[2][p]][k]; 93 else ban+=(k<lim)*res[ww[3][q]][k]; 94 }else if(fh==2){//<= 95 if(pos1==0) ban+=(k<=lim)*res[ww[0][i]][k]; 96 else if(pos1==1) ban+=(k<=lim)*res[ww[1][j]][k]; 97 else if(pos1==2) ban+=(k<=lim)*res[ww[2][p]][k]; 98 else ban+=(k<=lim)*res[ww[3][q]][k]; 99 }else if(fh==3){//> 100 if(pos1==0) ban+=(k>lim)*res[ww[0][i]][k]; 101 else if(pos1==1) ban+=(k>lim)*res[ww[1][j]][k]; 102 else if(pos1==2) ban+=(k>lim)*res[ww[2][p]][k]; 103 else ban+=(k>lim)*res[ww[3][q]][k]; 104 }else{//>= 105 if(pos1==0) ban+=(k>=lim)*res[ww[0][i]][k]; 106 else if(pos1==1) ban+=(k>=lim)*res[ww[1][j]][k]; 107 else if(pos1==2) ban+=(k>=lim)*res[ww[2][p]][k]; 108 else ban+=(k>=lim)*res[ww[3][q]][k]; 109 } 110 } 111 f[tim][i][j][p][q]+=(1.0-ban)*f[tim-1][i][j][p][q]; 112 int now; 113 if(pos2==0){ 114 if(i+val<=0) continue; 115 now=min(8,i+val); 116 f[tim][now][j][p][q]+=ban*f[tim-1][i][j][p][q]; 117 }else if(pos2==1){ 118 if(j+val<=0) continue; 119 int now=min(8,j+val); 120 f[tim][i][now][p][q]+=ban*f[tim-1][i][j][p][q]; 121 }else if(pos2==2){ 122 if(p+val<=0) continue; 123 now=min(8,p+val); 124 f[tim][i][j][now][q]+=ban*f[tim-1][i][j][p][q]; 125 }else{ 126 if(q+val<=0) continue; 127 now=min(8,q+val); 128 f[tim][i][j][p][now]+=ban*f[tim-1][i][j][p][q]; 129 } 130 } 131 } 132 } 133 } 134 } 135 void work4(int tim,int pos1,int fh,int lim,int pos2,int flag,int val){ 136 for(int i=1;i<=8;++i){ 137 for(int j=1;j<=8;++j){ 138 for(int p=1;p<=8;++p){ 139 for(int q=1;q<=8;++q){ 140 double ban=0.0; 141 for(int k=0;k<=16;++k){ 142 if(fh==1){//< 143 if(pos1==0) ban+=(k<lim)*res[ww[0][i]][k]; 144 else if(pos1==1) ban+=(k<lim)*res[ww[1][j]][k]; 145 else if(pos1==2) ban+=(k<lim)*res[ww[2][p]][k]; 146 else ban+=(k<lim)*res[ww[3][q]][k]; 147 }else if(fh==2){//<= 148 if(pos1==0) ban+=(k<=lim)*res[ww[0][i]][k]; 149 else if(pos1==1) ban+=(k<=lim)*res[ww[1][j]][k]; 150 else if(pos1==2) ban+=(k<=lim)*res[ww[2][p]][k]; 151 else ban+=(k<=lim)*res[ww[3][q]][k]; 152 }else if(fh==3){//> 153 if(pos1==0) ban+=(k>lim)*res[ww[0][i]][k]; 154 else if(pos1==1) ban+=(k>lim)*res[ww[1][j]][k]; 155 else if(pos1==2) ban+=(k>lim)*res[ww[2][p]][k]; 156 else ban+=(k>lim)*res[ww[3][q]][k]; 157 }else{//>= 158 if(pos1==0) ban+=(k>=lim)*res[ww[0][i]][k]; 159 else if(pos1==1) ban+=(k>=lim)*res[ww[1][j]][k]; 160 else if(pos1==2) ban+=(k>=lim)*res[ww[2][p]][k]; 161 else ban+=(k>=lim)*res[ww[3][q]][k]; 162 } 163 } 164 f[tim][i][j][p][q]+=(1.0-ban)*f[tim-1][i][j][p][q]; 165 for(int k=0,now;k<=2*val;++k){ 166 if(pos2==0){ 167 if(i+flag*k<=0) continue; 168 now=min(8,i+flag*k); 169 f[tim][now][j][p][q]+=ban*f[tim-1][i][j][p][q]*res[val][k]; 170 }else if(pos2==1){ 171 if(j+flag*k<=0) continue; 172 int now=min(8,j+flag*k); 173 f[tim][i][now][p][q]+=ban*f[tim-1][i][j][p][q]*res[val][k]; 174 }else if(pos2==2){ 175 if(p+flag*k<=0) continue; 176 now=min(8,p+flag*k); 177 f[tim][i][j][now][q]+=ban*f[tim-1][i][j][p][q]*res[val][k]; 178 }else{ 179 if(q+flag*k<=0) continue; 180 now=min(8,q+flag*k); 181 f[tim][i][j][p][now]+=ban*f[tim-1][i][j][p][q]*res[val][k]; 182 } 183 } 184 } 185 } 186 } 187 } 188 } 189 int main(){ 190 res[0][0]=1.0; 191 for(int i=1;i<=8;++i){ 192 for(int j=0;j<3;++j) 193 for(int k=j;k<=16;++k) 194 res[i][k]+=res[i-1][k-j]/3.0; 195 } 196 for(int i=0;i<4;++i){ 197 scanf("%s",ch+1); 198 for(int j=1;j<=8;++j) 199 ww[i][j]=ch[j]-'0'; 200 scanf("%d",&p[i]); 201 } 202 f[0][p[0]][p[1]][p[2]][p[3]]=100.0; 203 scanf("%d",&n); 204 for(int i=1;i<=n;++i){ 205 scanf("%s",ch+1); 206 int j=cal(); 207 scanf("%s",ch+1); 208 int len=strlen(ch+1); 209 if(len==2&&ch[1]!='>'&&ch[1]!='<'){ 210 int flag=(ch[1]=='+')?1:-1; 211 int val=ch[2]-'0'; 212 work1(i,j,flag*val); 213 }else if(len==3){ 214 int flag=(ch[1]=='+')?1:-1; 215 int val=ch[2]-'0'; 216 work2(i,j,flag,val); 217 }else{ 218 int fh=calc(),lim,k; 219 scanf("%d%s",&lim,ch+1); 220 k=cal(); 221 scanf("%s",ch+1); 222 int len=strlen(ch+1); 223 int flag=(ch[1]=='+')?1:-1; 224 int val=ch[2]-'0'; 225 if(len==2) work3(i,j,fh,lim,k,flag,val); 226 else work4(i,j,fh,lim,k,flag,val); 227 } 228 } 229 for(int k=0;k<4;++k){ 230 for(int i=1;i<=8;++i) 231 for(int j=1;j<=8;++j) 232 for(int p=1;p<=8;++p) 233 for(int q=1;q<=8;++q){ 234 if(k==0) ans[0][ww[0][i]]+=f[n][i][j][p][q]; 235 if(k==1) ans[1][ww[1][j]]+=f[n][i][j][p][q]; 236 if(k==2) ans[2][ww[2][p]]+=f[n][i][j][p][q]; 237 if(k==3) ans[3][ww[3][q]]+=f[n][i][j][p][q]; 238 } 239 } 240 for(int i=1;i<=8;++i) dead+=ans[0][i]; 241 dead=100.0-dead; 242 printf("%0.2lf ",dead); 243 for(int k=0;k<4;++k){ 244 for(int i=1;i<=8;++i) 245 printf("%0.2lf ",ans[k][i]); 246 puts(""); 247 } 248 return 0; 249 }
彩球问题:记忆化搜索+高精
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define int long long 6 using namespace std; 7 int n,k[20],n1,n2,n3; 8 bool vis[20][20][20][20]; 9 struct bigint{ 10 int m[105]; 11 bigint(){ 12 memset(m,0,sizeof(m)); 13 m[0]=1; 14 } 15 friend bigint operator + (bigint a,bigint b){ 16 int x=0; 17 bigint c; 18 c.m[0]=max(a.m[0],b.m[0]); 19 for(int i=1;i<=a.m[0]||i<=b.m[0];++i){ 20 c.m[i]=a.m[i]+b.m[i]+x; 21 x=c.m[i]/10; 22 c.m[i]%=10; 23 } 24 while(x) c.m[++c.m[0]]=x%10,x/=10; 25 return c; 26 } 27 friend void operator += (bigint &a,bigint b){ 28 a=a+b; 29 } 30 friend bigint operator * (int a,bigint b){ 31 int x=0; 32 bigint c; 33 c.m[0]=b.m[0]; 34 for(int i=1;i<=b.m[0];++i){ 35 c.m[i]=b.m[i]*a+x; 36 x=c.m[i]/10; 37 c.m[i]%=10; 38 } 39 while(x) c.m[++c.m[0]]=x%10,x/=10; 40 return c; 41 } 42 }f[20][20][20][20]; 43 void print(bigint a){ 44 for(int i=1;i<=a.m[0];++i){ 45 printf("%lld",a.m[a.m[0]-i+1]); 46 } 47 puts(""); 48 } 49 bigint dfs(int i,int j,int k,int x){ 50 bigint res; 51 res.m[0]=res.m[1]=1; 52 if(i+j+k==0) return res; 53 if(vis[i][j][k][x]) return f[i][j][k][x]; 54 bigint ans; 55 if(i) ans+=(i-(x==2))*dfs(i-1,j,k,1); 56 if(j) ans+=(j-(x==3))*dfs(i+1,j-1,k,2); 57 if(k) ans+=(k-(x==4))*dfs(i,j+1,k-1,3); 58 vis[i][j][k][x]=1; 59 return f[i][j][k][x]=ans; 60 } 61 signed main(){ 62 scanf("%lld",&n); 63 for(int i=1;i<=n;++i){ 64 scanf("%lld",&k[i]); 65 n1+=(k[i]==1); 66 n2+=(k[i]==2); 67 n3+=(k[i]==3); 68 } 69 print(dfs(n1,n2,n3,0)); 70 return 0; 71 }
邻面合并:
状压dp
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 int n,m,a[105][15],ans=0x3f3f3f3f; 7 int b[105],f[105][(1<<9)+5]; 8 bool judge(int now,int sta){ 9 bool flag=0; 10 for(int i=1;i<=m;++i){ 11 if(sta&(1<<(i-1))) flag=1; 12 if(a[now][i]==1&&flag==0) return 0; 13 if(!a[now][i]) flag=0; 14 if((sta&(1<<(i-1)))&&a[now][i]==0) return 0; 15 } 16 return 1; 17 } 18 int lowbit(int x){ 19 return x&-x; 20 } 21 int cal(int sta){ 22 int res=0; 23 while(sta>0){ 24 sta-=lowbit(sta); 25 ++res; 26 } 27 return res; 28 } 29 int main(){ 30 scanf("%d%d",&n,&m); 31 for(int i=1;i<=n;++i){ 32 for(int j=1;j<=m;++j){ 33 scanf("%d",&a[i][j]); 34 b[i]|=(a[i][j]<<(j-1)); 35 } 36 } 37 memset(f,0x3f,sizeof(f)); 38 f[0][0]=0; 39 for(int i=1;i<=n;++i){ 40 for(int s1=0;s1<(1<<m);++s1){ 41 if(!judge(i,s1)) continue; 42 for(int s2=0;s2<(1<<m);++s2){ 43 if(!judge(i-1,s2)) continue; 44 int cnt=cal(s1); 45 for(int j=1;j<=m;++j){ 46 if((s1&(1<<(j-1)))&&(s2&(1<<(j-1)))){ 47 int pos=j; 48 while(pos<=m&&a[i][pos]){ 49 if(pos!=j&&(s1&(1<<(pos-1)))) break; 50 ++pos; 51 } 52 --pos; 53 bool flag=0; 54 if(!(s2&(1<<pos)||(!a[i-1][pos+1]))) flag=1; 55 for(int k=j+1;k<=pos;++k){ 56 if(flag) break; 57 if((s2&(1<<(k-1)))||(!a[i-1][k])) flag=1; 58 } 59 if(!flag) --cnt; 60 } 61 } 62 f[i][s1]=min(f[i][s1],f[i-1][s2]+cnt); 63 if(i==n) ans=min(ans,f[i][s1]); 64 } 65 } 66 } 67 printf("%d ",ans); 68 return 0; 69 } 70 /* 71 4 4 72 1 1 1 0 73 1 1 0 1 74 0 0 1 1 75 0 0 1 1 76 4 77 78 4 4 79 1 1 1 0 80 0 1 1 1 81 0 1 1 1 82 0 1 1 1 83 2 84 85 5 4 86 1 1 0 1 87 1 1 1 1 88 1 1 0 1 89 0 0 1 1 90 0 0 1 1 91 4 92 93 8 4 94 1 1 1 1 95 0 1 0 0 96 0 1 0 0 97 1 1 1 0 98 1 1 1 0 99 1 1 1 1 100 0 1 1 1 101 0 0 1 1 102 5 103 104 8 4 105 1 1 1 1 106 0 1 1 0 107 0 1 0 0 108 1 1 1 0 109 1 1 1 0 110 1 1 1 1 111 0 1 1 1 112 0 0 1 1 113 6 114 115 4 11 116 1 1 1 0 1 1 0 0 1 0 0 117 1 1 0 0 1 1 0 0 1 1 0 118 1 0 0 0 1 0 0 0 1 1 1 119 1 1 1 1 1 0 0 1 1 0 0 120 */
123567:
杜教筛,啥都不会
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<unordered_map> 6 #include<cmath> 7 #define re register 8 using namespace std; 9 long long n,ans; 10 int N,prime[7000005],tot=0; 11 unordered_map<int,int>mp; 12 short mu[10000005]; 13 bool vis[10000005]; 14 inline void get_mu(re int N){ 15 vis[1]=mu[1]=1; 16 for(re int i=2;i<=N;++i){ 17 if(!vis[i]) prime[++tot]=i,mu[i]=-1; 18 for(re int j=1;i*prime[j]<=N;++j){ 19 vis[i*prime[j]]=1; 20 if(!(i%prime[j])) break; 21 mu[i*prime[j]]=-mu[i]; 22 } 23 mu[i]+=mu[i-1]; 24 } 25 } 26 inline int sum(re int x){ 27 if(x<=N) return mu[x]; 28 if(mp.find(x)!=mp.end()) return mp[x]; 29 re int res=1; 30 for(re int l=2,r;l<=x;l=r+1){ 31 r=x/(x/l); 32 res=res-sum(x/r)*(r-l+1); 33 } 34 return mp[x]=res; 35 } 36 signed main(){ 37 scanf("%lld",&n); 38 N=min(1e7,sqrt(n)); 39 get_mu(N); 40 for(re long long l=1,r;l*l<=n;l=r+1){ 41 r=sqrt(n/(n/(l*l))); 42 ans=ans+n/(r*r)*(sum(r)-sum(l-1)); 43 } 44 printf("%lld ",ans); 45 return 0; 46 }