CF1245 Hyakugoku and Ladders&Daniel and Spring Cleaning

https://codeforces.com/contest/1245/problem/E

题目大意:给定一张$10 \times 10$的方格图,每个奇数行的格子都与右边的格子相连,每个偶数行的格子都与左边的格子相连,每行顶端的格子都与上面的格子相连,有的格子之间存在梯子,可以选择走或不走,每次随机rand(1,6)一个走的步数,求最小到达终点的期望步数

Solution:

对于每个点先标一下号,由于要求最小期望且梯子是从底下向上搭的,所以考虑从终点往起点期望DP

设Dp[i]表示从这个点到达终点的期望步数

对于$dp[i] i \in [2,6]$需要特殊判断,然后如果有梯子,取从这个点到终点期望步数与从这个点走梯子到达的位置到终点的期望步数的最小值即可

CODE:

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define dwn(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
double dp[104];
int id[15][15],tot,to[150];
int main(){
    rep(i,1,10){
        if(i&1) rep(j,1,10) id[i][j]=++tot;
        else dwn(j,10,1) id[i][j]=++tot;
    }
    rep(i,1,10){
        int a; 
        rep(j,1,10) scanf("%d",&a),to[id[i][j]]=id[i-a][j];
    }
    rep(i,2,6){
        double s=0;
        rep(j,1,i-1) s+=(dp[j]+1)/6.00;
        s=(s+(7-i)/6.00)/(double(i-1)/6.00);
        dp[i]=s;
    }
    rep(i,7,tot){
        rep(j,1,6) dp[i]+=(dp[i-j]+1)/6.00;
        if(to[i]){
            double s=0;
            if(to[i]<=6) s=dp[to[i]];
            else rep(j,1,6) s+=(dp[to[i]-j]+1)/6.00;
            dp[i]=min(dp[i],s);
        }
    }
    printf("%.10lf",dp[tot]);
    return 0;
}

F:

题目大意:对于$a,b \in[l,r]$,求a+b=a^b的方案数

设$f(x,y)$表示对于第一个数只能取到x,对于第二个数只能取到y的满足答案的方案数

容斥得到$ans=f(r,r)-2 \times f(l-1,r)+f(l-1,l-1)$

然后跑一跑数位DP即可

CODE:

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define int long long
using namespace std;
int dp[33][2][2],n1[33],n2[33],tot1,tot2;
int DigitDp(int x,int y,int z){
    if(!x) return 1;
    if(dp[x][y][z]!=-1) return dp[x][y][z];
    int res=0,ex=y?n1[x]:1,ey=z?n2[x]:1;
    rep(i,0,ex){
        rep(j,0,ey){
            if(i&j) continue;
            res+=DigitDp(x-1,y&&ex==i,z&&ey==j);
        }
    }
//    cout<<x<<" "<<y<<" "<<z<<" "<<res<<endl;
    dp[x][y][z]=res;
    return res; 
}
int f(int x,int y){
//    cout<<endl; cout<<endl;
    if(x<0) return 0;tot1=tot2=0;
    memset(n1,0,sizeof(n1));
    memset(n2,0,sizeof(n2));
    memset(dp,-1,sizeof(dp));
    while(x) n1[++tot1]=x&1,x>>=1;
    while(y) n2[++tot2]=y&1,y>>=1;
    return DigitDp(tot2,1,1);
}
main(){
    int t; scanf("%lld",&t);
    rep(i,1,t){
        int l,r; scanf("%lld%lld",&l,&r);
        printf("%lld\n",f(r,r)-2*f(l-1,r)+f(l-1,l-1));
    }
    return 0;
}

 

posted @ 2019-11-04 13:54  niolle  阅读(184)  评论(0编辑  收藏  举报