LOADING

加载过慢请开启缓存,浏览器默认开启

daily 3

2023/4/2 daily Codeforces

今天数位dp主场惹

CF 1051D

常见的范围dp,思想比较简单

$dp[i][j][0/1]$表示当前是第i列,然后有j组,当前列两个方块颜色相同/不同

那么转移方程很好写

$dp[i][j][0]=(dp[i-1][j-1][0]+dp[i-1][j][0]+2*dp[i-1][j][1])$

$dp[i][j][1]=(2*dp[i-1][j-1][0]+dp[i-1][j][1]+dp[i-1][j-2][1])$

ll dp[N][2*N][2];//0 means equal 1 means not equal
void solve(){
  int n,k;
  cin>>n>>k;
  int cur,nxt;
  dp[1][1][0]=dp[1][2][1]=2;
  for(int i=2;i<=n;++i){
    for(int j=1;j<=k;++j){
        if(j==1){
            dp[i][j][0]=2;
        }else{
            dp[i][j][0]=(dp[i-1][j-1][0]+2*dp[i-1][j][1]+dp[i-1][j][0])%MOD;
            dp[i][j][1]=(dp[i-1][j][1]+dp[i-1][j-2][1]+2*dp[i-1][j-1][0])%MOD;
        }
    }
  }
  cout<<(dp[n][k][0]+dp[n][k][1])%MOD<<'\n';
  return;
}

CF 855E
dp[base][pos][sta]表示当前的的基数下,当前遍历到第pos位,之前的情况是sta

那么转移很正常,就按数位dp的板子套一哈就好了

ll dp[11][70][1024];
void solve(){
  int q;
  cin>>q;
  int base;
  memset(dp,-1,sizeof(dp));
  vector<int>num(70);
  function<ll(int,int,int,int)>dfs=[&](int pos,int sta,int lead,int flag){
    if(!pos)return (ll)!sta;
    if(!lead&&!flag&&dp[base][pos][sta]!=-1){
        return dp[base][pos][sta];
    }
    ll res=0;
    int lim=flag?num[pos]:base-1;
    for(int i=0;i<=lim;++i){
        res+=dfs(pos-1,(lead&&!i)?0:(sta^(1<<i)),lead&&(!i),flag&&(i==(lim)));
    }
    if(!lead&&!flag){
        dp[base][pos][sta]=res;
    }
    return res;
  };
  ll l,r;
  function<ll(ll)>get=[&](ll x){
    int pos=0;
    while(x){
        num[++pos]=x%base;
        x/=base;
    }
    return dfs(pos,0,1,1);
  };
  while(q--){
    cin>>base>>l>>r;
    ll right=get(r),left=get(l-1);
    cout<<get(r)-get(l-1)<<'\n';
  }
  return;
}

CF 55D
首先1-9的乘积为2520,然后对于一个数A,你等价于A%2520

之后你还需要存一哈mod的值,注意到2520的因数只有48个,那么就搞这48个就吼了(只有这48个满足情况)

ll dp[50][N+1][50];
ll gcd(ll a,ll b){
    return b?a:gcd(b,a%b);
}
void solve(){
  int t;cin>>t;
  memset(dp,-1,sizeof(dp));
  vector<int>mp(N+1);
  int cnt=0;
  for(int i=1;i<=N;++i){
    if(2520%i==0){
        mp[i]=++cnt;
    }
  }
  vector<int>num(50);
  function<ll(int,int,int,int)>dfs=[&](int pos,int pre,int mod,int flag){
    if(!pos)return (ll)(pre%mod==0);
    if(!flag&&dp[pos][pre][mp[mod]]!=-1){
        return dp[pos][pre][mp[mod]];
    }
    ll res=0;
    int lim=flag?num[pos]:9;
    for(int i=0;i<=lim;++i){
        res+=dfs(pos-1,(pre*10+i)%N,i==0?mod:mod*i/gcd(mod,i),flag&&(i==lim));
    }
    if(!flag){
        dp[pos][pre][mp[mod]]=res;
    }
    return res;
  };
  function<ll(ll)>get=[&](ll x){
    int pos=0;
    while(x){
        num[++pos]=x%10;
        x/=10;
    }
    return dfs(pos,0,1,1);
  };    
  while(t--){
    ll l,r;
    cin>>l>>r;
    cout<<get(r)-get(l-1)<<'\n';
  }
  return;
}

明天三面阿里了,有点紧脏。啊啊啊啊,干巴爹