zoukankan      html  css  js  c++  java
  • 数位dp初探

    我这种蒟蒻就一直不会写数位dp。。

    于是开了个坑。。

    1833: [ZJOI2010]count 数字计数

    这道被KPM大爷说是入门题。。嗯似乎找找规律然后减掉0的情况后乱搞就可以了。。(但是还是写了很久TAT

    #include<cstring>
    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<cmath>
    #include<algorithm>
    #define rep(i,l,r) for (int i=l;i<=r;i++)
    #define down(i,l,r) for (int i=l;i>=r;i--)
    #define clr(x,y) memset(x,y,sizeof(x))
    #define low(x) (x&(-x)) 
    #define maxn 505
    #define inf int(1e9)
    #define mm 1000000007
    #define ll long long
    using namespace std;
    ll ans[10][2];
    ll a,b,bin[18];
    ll read(){
        ll x=0,f=1; char ch=getchar();
        while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
        while (isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    int get(ll x){
        if (x==0) return 1;
        int ans=0; 
        while(x){ans++; x/=10;}
        return ans;
    }
    void cal(ll x,int f){
        int L,l=get(x),a; L=l;
        rep(i,0,9) ans[i][f]=(l-1)*bin[l-2];
        rep(i,1,l-2) ans[0][f]-=bin[i];
        while (l){
            a=x/bin[l-1];
            if (l==L) rep(i,1,a-1) {
                ans[i][f]+=bin[l-1];
                if (l-2>=0) rep(j,0,9) ans[j][f]+=1LL*(l-1)*bin[l-2];
            }
            if (l!=L) rep(i,0,a-1) {
                ans[i][f]+=bin[l-1];
                if (l-2>=0) rep(j,0,9) ans[j][f]+=1LL*(l-1)*bin[l-2]; 
            }
            ans[a][f]+=x%bin[l-1]+1;
            x=x%bin[l-1];
            l--;
        }
    }
    int main(){
        bin[0]=1; rep(i,1,13) bin[i]=bin[i-1]*10; 
        a=read(); b=read();
        cal(a-1,0); 
        cal(b,1);
        rep(i,0,8) printf("%lld ",ans[i][1]-ans[i][0]);
        printf("%lld
    ",ans[9][1]-ans[9][0]);
        return 0;
    } 
    View Code

    1026: [SCOI2009]windy数

    这道写个dp f[i][j]表示第i位最前一位数是j,特判一下0的情况。。

    #include<cstring>
    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<cmath>
    #include<algorithm>
    #define rep(i,l,r) for (int i=l;i<=r;i++)
    #define down(i,l,r) for (int i=l;i>=r;i--)
    #define clr(x,y) memset(x,y,sizeof(x))
    #define low(x) (x&(-x)) 
    #define maxn 505
    #define inf int(1e9)
    #define mm 1000000007
    #define ll long long
    using namespace std;
    int f[15][10],bin[15];
    int a,b;
    int read(){
        int x=0,f=1; char ch=getchar();
        while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
        while (isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    int get(ll x){
        if (x==0) return 1;
        int ans=0; 
        while(x){ans++; x/=10;}
        return ans;
    }
    int cal(int x){
        int L,l=get(x),ans=0,a,tmp=-100; L=l;
        if (l>1) ans++;//0的情况
        rep(i,1,l-1) {
            rep(j,1,9) ans+=f[i][j];
        }
        while (l){
            a=x/bin[l-1];
            if (l==L) rep(i,1,a-1) if (abs(i-tmp)>=2){
                rep(j,0,9) if (abs(i-j)>=2) ans+=f[l-1][j];
            }
            if (l!=L) rep(i,0,a-1) if (abs(i-tmp)>=2){
                rep(j,0,9) if (abs(i-j)>=2) ans+=f[l-1][j];
            }
            if (l==1) rep(i,0,a) if (abs(tmp-i)>=2) ans++;  
            if (abs(tmp-a)<2) break;
            tmp=a;
            x%=bin[l-1];
            l--;
        }
        return ans;
    }
    int main(){
        bin[0]=1; rep(i,1,9) bin[i]=bin[i-1]*10;
        a=read(); b=read();
        int l=get(b);
        rep(i,0,9) f[1][i]=1;
        rep(i,1,9) rep(j,0,9) if (f[i][j]){
            rep(k,0,9) if (abs(j-k)>=2) f[i+1][k]+=f[i][j];
        }
        printf("%d
    ",cal(b)-cal(a-1));
        return 0;
    } 
    View Code

    1072: [SCOI2007]排列perm

    为什么我一直认为这道是状压。。 f[s][i]表示当前状态是s,模数为i。然后枚举每一个数是否被选过转移就可以了。

    最后除掉相同数字个数的阶乘。

    #include<cstring>
    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<cmath>
    #include<algorithm>
    #define rep(i,l,r) for (int i=l;i<=r;i++)
    #define down(i,l,r) for (int i=l;i>=r;i--)
    #define clr(x,y) memset(x,y,sizeof(x))
    #define low(x) (x&(-x)) 
    #define maxn 505
    #define inf int(1e9)
    #define mm 1000000007
    #define ll long long
    using namespace std;
    int f[1050][1005];
    int n,t,l,bin[20],a[20],num[20],p[20],ans;
    char s[15];
    int read(){
        int x=0,f=1; char ch=getchar();
        while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
        while (isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    int main(){
        t=read();
        bin[0]=1; rep(i,1,10) bin[i]=bin[i-1]*2;
        p[0]=1; rep(i,1,10) p[i]=p[i-1]*i;
        while (t--){
            clr(f,0); clr(num,0);
            scanf("%s",s); l=strlen(s);
            int d=read();
            rep(i,0,l-1) a[i]=s[i]-'0',num[a[i]]++;
            //printf("%d
    ",bin[l]-1);
            f[0][0]=1; 
            rep(s,0,bin[l]-1) rep(j,0,d-1) if (f[s][j]){
                rep(k,0,l-1) if ((s&bin[k])==0) f[s+bin[k]][(j*10+a[k])%d]+=f[s][j];
            }
            ans=f[bin[l]-1][0];
            rep(i,0,9) if (num[i]) ans/=p[num[i]];
            printf("%d
    ",ans);
        }
        return 0;
    } 
    View Code

    2425: [HAOI2010]计数

    题目其实就是给你一些数字让你用这些数字构造一个个比给定数小的数。。

    比如说我现在这一位最高为x,那就取0~x-1(可以有前导0)为这一位然后剩下的数自由组合。

    对于这个自由组合,比如剩下有n位,这个数字还剩下有x个,那每一次就乘上C(n,x)然后n-=x。

    #include<cstring>
    #include<iostream>
    #include<cstdio>
    #include<queue>
    #include<cmath>
    #include<algorithm>
    #define rep(i,l,r) for (int i=l;i<=r;i++)
    #define down(i,l,r) for (int i=l;i>=r;i--)
    #define clr(x,y) memset(x,y,sizeof(x))
    #define low(x) (x&(-x)) 
    #define maxn 505
    #define inf int(1e9)
    #define mm 1000000007
    #define ll long long
    using namespace std;
    ll c[55][55],ans;
    int cnt[10],a[55];
    char s[55];
    int read(){
        int x=0,f=1; char ch=getchar();
        while (!isdigit(ch)) {if (ch=='-') f=-1; ch=getchar();}
        while (isdigit(ch)) {x=x*10+ch-'0'; ch=getchar();}
        return x*f;
    }
    ll cal(int n){
        ll ans=1;
        int now=n;
        rep(i,0,9) ans*=c[now][cnt[i]],now-=cnt[i];
        return ans; 
    }
    int main(){
        c[0][0]=1; 
        rep(i,1,50) {
            c[i][0]=1;
            rep(j,1,50) c[i][j]=c[i-1][j-1]+c[i-1][j];
        }
        scanf("%s",s); int l=strlen(s);
        rep(i,0,l-1) a[i+1]=s[i]-'0',cnt[a[i+1]]++;
        rep(i,1,l) {
            rep(j,0,a[i]-1) if (cnt[j]){
                cnt[j]--;
                ans+=cal(l-i);
                cnt[j]++;
            }
            cnt[a[i]]--;
        }
        printf("%lld
    ",ans);
        return 0;
    } 
    View Code

    BZOJ1799: [Ahoi2009]self 同类分布

    http://www.cnblogs.com/ctlchild/p/5126952.html

    (还有几道题目慢慢填TAT。。。

  • 相关阅读:
    NSURLSession实现文件上传
    JS中如何判断null、undefined与NaN
    jquery
    url操作等
    设计模式
    javaScript类型转换
    jQuery.noop
    JavaScript严谨模式(Strict Mode)提升开发效率和质量
    Data URI
    e.target e.currenttarget
  • 原文地址:https://www.cnblogs.com/ctlchild/p/5131420.html
Copyright © 2011-2022 走看看