【JZOJ6103】Diyiti

Description

在这里插入图片描述

Solution

考虑两个序列(下标为 1 1 1~ n n n,左边为高位):
x : 1100101 x:1100101 x:1100101
y : 1001011 y:1001011 y:1001011
        u    v \ \ \ \ \ \ \ u\ \ v        u  v
它的距离如何计算?
先找到最小的 v v v使得 x v &lt; y v x_v&lt;y_v xv<yv,再找到比 v v v小最大的 u u u使得 x u &gt; y u x_u&gt;y_u xu>yu,那么最优策略是将 x i = 1 ( i &gt; u ) x_i=1(i&gt;u) xi=1(i>u)全部抹掉,然后使 x − 1 x-1 x1,使得 ∀ i &gt; u x i = 1 \forall_{i&gt;u} x_i=1 i>uxi=1,最后把 y i = 1 ( i &gt; u ) y_i=1(i&gt;u) yi=1(i>u) x i x_i xi抹掉。
c n t x cnt_x cntx c n t y cnt_y cnty分别位 x x x y y y 1 1 1的个数,距离即为 c n t x − c n t y + n − u cnt_x-cnt_y+n-u cntxcnty+nu
有了这个我们就可以dp了,设 f i , j = 0..1 , k = 0..2 f_{i,j=0..1,k=0..2} fi,j=0..1,k=0..2表示从后往前做到了第 i i i位(低位往高位转移), j j j表示不考虑 i i i~ n n n位时 x x x是否小于 y y y j = 1 j=1 j=1表示小于), k = 2 k=2 k=2表示 u u u v v v都还没出现, k = 1 k=1 k=1表示 v v v已出现但 u u u未出现, k = 2 k=2 k=2表示 u u u v v v都已出现。
f f f的转移直接考虑状态意义即可。
重要的是距离和的转移,重新考虑 + n − u +n-u +nu的含义,它代表在 k &gt; 0 k&gt;0 k>0时当前的 i i i都会对前面 u u u有贡献,所以在这种情况下直接贡献1的距离即可。

Code

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define fo(i,j,k) for(int i=j;i<=k;++i)
#define fd(i,j,k) for(int i=j;i>=k;--i)
using namespace std;
typedef long long ll;
const int N=550,mo=1e9+7;
char s[N];
void inc(int &x,int y){
	x=x+y>=mo?x+y-mo:x+y;
}
struct node{
	int f,g;
	node(int _f=0,int _g=0) {f=_f,g=_g;}
	void up(const node x,int t){
		inc(f,x.f),inc(g,x.g);
		for(;t--;inc(g,x.f)); 
	}
}f[N][2][3];
int main()
{
	scanf("%s",s+1);
	int n=strlen(s+1);
	f[n+1][0][0]=f[n+1][0][2]=f[n+1][1][0]=f[n+1][1][2]=node(1,0);//序列可以同时不存在u,v。
	fd(i,n,1){
		int c=s[i]-'0';
		fo(j,0,1){
			int xr=!j?c:1;
			fo(k,0,2)//k=0:u,v k=1:v k=2:
			fo(x,0,xr){
				int yl=k==1?x:0,yr=!k?x:1;
				fo(y,yl,yr){
					int t=x-y+(k>0),p=j|(x<c),zt;//t为这一位的距离贡献
					if(!k) zt=1|(x>y?2:0);//k=0,这一位x>y时由1转移,否则由0转移。
					else zt=k&1?(x<y?4:2):4;//k=1,这一位x<y时由2转移,否则由1转移。
					fo(l,0,2) if(zt&(1<<l)) f[i][j][k].up(f[i+1][p][l],t);
				}
			}
		}
	}
	printf("%d",f[1][0][0].g);
}

posted @ 2019-04-03 22:33  sadstone  阅读(40)  评论(0编辑  收藏  举报