zoukankan      html  css  js  c++  java
  • 数位dp 专题

    数位dp 专题

    先来模板:

    int dfs(int i,int s,bool e) ///枚举第i位,第i位前一位的数字为s,e表示前缀是否已达到上界。(如果未达到,则枚举0000...~9999..,反之枚举0000...~abcd...)
    {
        if(i==-1) return 1;
        if(!e&&~f[i][s]) return f[i][s];/// f记录的是位数为i,前一数字为s的0000..~9999...的符合条件的个数
        int res=0;
        int u=e?num[i]:9;
        REP(d,0,u){
            res+=dfs(i-1,d,e&&d==u));
        }
        return d==u?res:f[i][s]=res;
    }
    View Code

     C题:

    http://acm.hust.edu.cn/vjudge/contest/view.action?cid=70324#problem/C

    求[L,R]中不含62和4的数的个数。

    f[i][s]为符合条件的数的个数,第一维i表示当前位数,第二维s表示前一位(第i+1位)的数字。

    总算是过了第一道数位dp的题。。。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<vector>
    #include<stack>
    #include<queue>
    #include<set>
    #include<map>
    #include<string>
    #include<math.h>
    #include<cctype>
    #define ll long long
    #define REP(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
    #define REPP(i,a,b,t) for(int (i)=(a);(i)<=(b);(i)+=(t))
    #define rep(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)
    #define repp(i,a,b,t) for(int (i)=(a);(i)>=(b);(i)-=(t))
    #define PII pair<int,int>
    #define fst first
    #define snd second
    #define MP make_pair
    #define PB push_back
    #define RI(x) scanf("%d",&(x))
    #define RII(x,y) scanf("%d%d",&(x),&(y))
    #define RIII(x,y,z) scanf("%d%d%d",&(x),&(y),&(z))
    #define DRI(x) int (x);scanf("%d",&(x))
    #define DRII(x,y) int (x),(y);scanf("%d%d",&(x),&(y))
    #define DRIII(x,y,z) int (x),(y),(z);scanf("%d%d%d",&(x),&(y),&(z))
    #define RS(x) scanf("%s",x)
    #define RSS(x,y) scanf("%s%s",x,y)
    #define DRS(x) char x[maxn];scanf("%s",x)
    #define DRSS(x,y) char x[maxn],y[maxn];scanf("%s%s",x,y)
    #define MS0(a) memset((a),0,sizeof((a)))
    #define MS1(a) memset((a),-1,sizeof((a)))
    #define MS(a,b) memset((a),(b),sizeof((a)))
    #define ALL(v) v.begin(),v.end()
    #define SZ(v) (int)(v).size()
    
    using namespace std;
    
    const int maxn=1000100;
    const int INF=(1<<29);
    const double EPS=0.0000000001;
    const double Pi=acos(-1.0);
    
    int L,R;
    int num[110];
    int f[110][11];
    
    int dfs(int i,int s,bool e)
    {
        if(i==-1) return 1;
        if(!e&&~f[i][s]) return f[i][s];
        int res=0;
        int u=e?num[i]:9;
        REP(d,0,u){
            if(d==4||(s==6&&d==2)) continue;
            res+=dfs(i-1,d,e&&d==u);
        }
        return e?res:f[i][s]=res;
    }
    
    int F(int n)
    {
        MS0(num);
        int len=0;
        while(n){
            num[len++]=n%10;
            n/=10;
        }
        MS1(f);
        return dfs(len-1,0,1);
    }
    
    int main()
    {
        //freopen("in.txt","r",stdin);
        while(cin>>L>>R,(L||R)){
            cout<<F(R)-F(L-1)<<endl;
        }
        return 0;
    }
    View Code

     D题:

    求[0,N]中含有49的数的个数。

    先求不含49的个数k,注意总个数是N+1,(区间为[0,N],0也算一个)。

    注意用unsigned long long。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<vector>
    #include<stack>
    #include<queue>
    #include<set>
    #include<map>
    #include<string>
    #include<math.h>
    #include<cctype>
    #define ll unsigned long long
    //#define ull unsigned long long
    #define REP(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
    #define REPP(i,a,b,t) for(int (i)=(a);(i)<=(b);(i)+=(t))
    #define rep(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)
    #define repp(i,a,b,t) for(int (i)=(a);(i)>=(b);(i)-=(t))
    #define PII pair<int,int>
    #define fst first
    #define snd second
    #define MP make_pair
    #define PB push_back
    #define RI(x) scanf("%d",&(x))
    #define RII(x,y) scanf("%d%d",&(x),&(y))
    #define RIII(x,y,z) scanf("%d%d%d",&(x),&(y),&(z))
    #define DRI(x) int (x);scanf("%d",&(x))
    #define DRII(x,y) int (x),(y);scanf("%d%d",&(x),&(y))
    #define DRIII(x,y,z) int (x),(y),(z);scanf("%d%d%d",&(x),&(y),&(z))
    #define RS(x) scanf("%s",x)
    #define RSS(x,y) scanf("%s%s",x,y)
    #define DRS(x) char x[maxn];scanf("%s",x)
    #define DRSS(x,y) char x[maxn],y[maxn];scanf("%s%s",x,y)
    #define MS0(a) memset((a),0,sizeof((a)))
    #define MS1(a) memset((a),-1,sizeof((a)))
    #define MS(a,b) memset((a),(b),sizeof((a)))
    #define ALL(v) v.begin(),v.end()
    #define SZ(v) (int)(v).size()
    
    using namespace std;
    
    const int maxn=1000100;
    const int INF=(1<<29);
    const double EPS=0.0000000001;
    const double Pi=acos(-1.0);
    
    ll N;
    int num[120];
    ll f[120][120];
    
    ll dfs(int i,int s,bool e)
    {
        if(i==-1) return 1;
        if(!e&&~f[i][s]) return f[i][s];
        ll res=0;
        int u=e?num[i]:9;
        REP(d,0,u){
            if(s==4&&d==9) continue;
            res+=dfs(i-1,d,e&&d==u);
        }
        return e?res:f[i][s]=res;
    }
    
    ll F(ll N)
    {
        MS0(num);
        int len=0;
        ll t=N;
        while(t){
            num[len++]=t%10;
            t/=10;
        }
        MS1(f);
        return N+1-dfs(len-1,0,1);
    }
    
    int main()
    {
        //freopen("in.txt","r",stdin);
        DRI(T);
        while(T--){
            cin>>N;
            cout<<F(N)<<endl;
        }
        return 0;
    }
    View Code

     E题:

    求[L,R]中二进制表示中0的个数比1的个数多或等的数的个数。

    f[i][s][one][zero]:i表示当前位数,s,one,zero分别表示之前的数字,之前的1的个数,之前的0的个数(不含前导0)。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<vector>
    #include<stack>
    #include<queue>
    #include<set>
    #include<map>
    #include<string>
    #include<math.h>
    #include<cctype>
    #define ll long long
    #define REP(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
    #define REPP(i,a,b,t) for(int (i)=(a);(i)<=(b);(i)+=(t))
    #define rep(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)
    #define repp(i,a,b,t) for(int (i)=(a);(i)>=(b);(i)-=(t))
    #define PII pair<int,int>
    #define fst first
    #define snd second
    #define MP make_pair
    #define PB push_back
    #define RI(x) scanf("%d",&(x))
    #define RII(x,y) scanf("%d%d",&(x),&(y))
    #define RIII(x,y,z) scanf("%d%d%d",&(x),&(y),&(z))
    #define DRI(x) int (x);scanf("%d",&(x))
    #define DRII(x,y) int (x),(y);scanf("%d%d",&(x),&(y))
    #define DRIII(x,y,z) int (x),(y),(z);scanf("%d%d%d",&(x),&(y),&(z))
    #define RS(x) scanf("%s",x)
    #define RSS(x,y) scanf("%s%s",x,y)
    #define DRS(x) char x[maxn];scanf("%s",x)
    #define DRSS(x,y) char x[maxn],y[maxn];scanf("%s%s",x,y)
    #define MS0(a) memset((a),0,sizeof((a)))
    #define MS1(a) memset((a),-1,sizeof((a)))
    #define MS(a,b) memset((a),(b),sizeof((a)))
    #define ALL(v) v.begin(),v.end()
    #define SZ(v) (int)(v).size()
    
    using namespace std;
    
    const int maxn=1000100;
    const int INF=(1<<29);
    const double EPS=0.0000000001;
    const double Pi=acos(-1.0);
    
    ll L,R;
    int num[70];
    ll f[70][2][70][70];
    
    ll dfs(int i,int s,int one,int zero,bool e)
    {
        if(i==-1) return one<=zero;
        if(!e&&~f[i][s][one][zero]) return f[i][s][one][zero];
        ll res=0;
        int u=e?num[i]:1;
        REP(d,0,u){
            if(d==0) res+=dfs(i-1,d,one,zero+(one?1:0),e&&d==u);
            else res+=dfs(i-1,d,one+1,zero,e&&d==u);
        }
        return e?res:f[i][s][one][zero]=res;
    }
    
    ll F(ll n)
    {
        MS0(num);
        int len=0;
        while(n){
            num[len++]=n%2;
            n>>=1;
        }
        MS1(f);
        return dfs(len-1,0,0,0,1);
    }
    
    int main()
    {
        //freopen("in.txt","r",stdin);
        while(cin>>L>>R){
            cout<<F(R)-F(L-1)<<endl;
        }
        return 0;
    }
    View Code

     F题:

    求[L,R]中平衡数的个数。平衡数即以某位作为支点,两边数的位置作为权值,距离支点的距离为力臂,天平平衡的数。如4139,支点为3,4*2+1*1=9*1,是平衡数。

    做完这题后对dfs(i,s,e)的模板有了更深的理解,中间的s并不只是第i+1位的数,而是第i+1位的状态,这个状态可以是一个变量也可以是多个变量,可以是第i+1位的数,也可以是第i+1位的某一状态特征。

    如本题的s为:(sum,pos),故f[i][sum][pos]。

    解决本题还需首先明确一个事实,每个平衡数有且只有一个支点,但由于计算是不考虑前导0,所以会多算了00,000,0000等,因此最终答案需减去len-1。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<vector>
    #include<stack>
    #include<queue>
    #include<set>
    #include<map>
    #include<string>
    #include<math.h>
    #include<cctype>
    #define ll long long
    #define REP(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
    #define REPP(i,a,b,t) for(int (i)=(a);(i)<=(b);(i)+=(t))
    #define rep(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)
    #define repp(i,a,b,t) for(int (i)=(a);(i)>=(b);(i)-=(t))
    #define PII pair<int,int>
    #define fst first
    #define snd second
    #define MP make_pair
    #define PB push_back
    #define RI(x) scanf("%d",&(x))
    #define RII(x,y) scanf("%d%d",&(x),&(y))
    #define RIII(x,y,z) scanf("%d%d%d",&(x),&(y),&(z))
    #define DRI(x) int (x);scanf("%d",&(x))
    #define DRII(x,y) int (x),(y);scanf("%d%d",&(x),&(y))
    #define DRIII(x,y,z) int (x),(y),(z);scanf("%d%d%d",&(x),&(y),&(z))
    #define RS(x) scanf("%s",x)
    #define RSS(x,y) scanf("%s%s",x,y)
    #define DRS(x) char x[maxn];scanf("%s",x)
    #define DRSS(x,y) char x[maxn],y[maxn];scanf("%s%s",x,y)
    #define MS0(a) memset((a),0,sizeof((a)))
    #define MS1(a) memset((a),-1,sizeof((a)))
    #define MS(a,b) memset((a),(b),sizeof((a)))
    #define ALL(v) v.begin(),v.end()
    #define SZ(v) (int)(v).size()
    
    using namespace std;
    
    const int maxn=1000100;
    const int INF=(1<<29);
    const double EPS=0.0000000001;
    const double Pi=acos(-1.0);
    
    ll L,R;
    int num[30];
    const ll zero=2100;
    ll f[30][4200][30];
    
    ll dfs(int i,int sum,int pos,bool e)
    {
        if(i==-1) return sum==zero;
        if(sum<zero) return 0; ///这个剪枝并没有多大效果
        if(!e&&~f[i][sum][pos]) return f[i][sum][pos];
        ll res=0;
        int u=e?num[i]:9;
        REP(d,0,u){
            res+=dfs(i-1,sum+(i-pos)*d,pos,e&&d==u);
        }
        return e?res:f[i][sum][pos]=res;
    }
    
    ll F(ll n)
    {
        MS0(num);
        int len=0;
        while(n){
            num[len++]=n%10;
            n/=10;
        }
        MS1(f);
        ll res=0;
        REP(i,0,len-1) res+=dfs(len-1,zero,i,1);
        return res-(len-1);
    }
    
    int main()
    {
        freopen("in.txt","r",stdin);
        DRI(T);
        while(T--){
            cin>>L>>R;
            cout<<F(R)-F(L-1)<<endl;
        }
        return 0;
    }
    View Code

     xdoj1076:

    http://acm.xidian.edu.cn/problem.php?id=1076

    数位dp,水题。注意前导0的情况,即0000135,处理方法是判断s和d是否都为0,因为s==0&&d==1,3,5可能符合条件,而s==1,3,5&&d==0一定不符合条件。

    注意unsigned long long .

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<vector>
    #include<stack>
    #include<queue>
    #include<set>
    #include<map>
    #include<string>
    #include<math.h>
    #include<cctype>
    #define ll unsigned long long
    #define REP(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
    #define REPP(i,a,b,t) for(int (i)=(a);(i)<=(b);(i)+=(t))
    #define rep(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)
    #define repp(i,a,b,t) for(int (i)=(a);(i)>=(b);(i)-=(t))
    #define PII pair<int,int>
    #define fst first
    #define snd second
    #define MP make_pair
    #define PB push_back
    #define RI(x) scanf("%d",&(x))
    #define RII(x,y) scanf("%d%d",&(x),&(y))
    #define RIII(x,y,z) scanf("%d%d%d",&(x),&(y),&(z))
    #define DRI(x) int (x);scanf("%d",&(x))
    #define DRII(x,y) int (x),(y);scanf("%d%d",&(x),&(y))
    #define DRIII(x,y,z) int (x),(y),(z);scanf("%d%d%d",&(x),&(y),&(z))
    #define RS(x) scanf("%s",x)
    #define RSS(x,y) scanf("%s%s",x,y)
    #define DRS(x) char x[maxn];scanf("%s",x)
    #define DRSS(x,y) char x[maxn],y[maxn];scanf("%s%s",x,y)
    #define MS0(a) memset((a),0,sizeof((a)))
    #define MS1(a) memset((a),-1,sizeof((a)))
    #define MS(a,b) memset((a),(b),sizeof((a)))
    #define ALL(v) v.begin(),v.end()
    #define SZ(v) (int)(v).size()
    
    using namespace std;
    
    const int maxn=1000100;
    const int INF=(1<<29);
    const double EPS=0.0000000001;
    const double Pi=acos(-1.0);
    
    char str[52];
    int num[52];
    ll f[52][20];
    
    ll dfs(int i,int s,bool e)
    {
        if(i==-1) return 1;
        if(!e&&~f[i][s]) return f[i][s];
        ll res=0;
        int u=e?num[i]:9;
        REP(d,0,u){
            if(d==1||d==3||d==5) res+=dfs(i-1,d,e&&u==d);
            else if(d==0&&s==0) res+=dfs(i-1,d,e&&u==d);
        }
        return e?res:f[i][s]=res;
    }
    
    int main()
    {
        freopen("in.txt","r",stdin);
        while(~RS(str)){
            int len=strlen(str);
            MS0(num);
            REP(i,0,len-1) num[i]=str[len-1-i]-'0';
            MS1(f);
            printf("%llu
    ",dfs(len-1,0,1)-1);
        }
        return 0;
    }
    View Code

     ##### 以上几个题的代码中每次计算F函数时都对f进行了初始化,然而完全没有必要!!!因为f的值和n并没有什么关系,并不需要每次都初始化,而每次都初始化大大增加了复杂度。比如接下来的这道题就TLE了!!!!!!!!!!!!#############

    A题:

    http://acm.hust.edu.cn/vjudge/contest/view.action?cid=70324#problem/A

    求[L,R]中符合条件的数的个数,条件为:一个数n,能被它的每一位非0的数整除。

    思路:能被n的每一位整除即能被它所有位的lcm整除,因此最后判断条件为n%lcm,而n太大不能作为状态,然而lcm(1,2,..,9)=2520,lcm一定是2520的约数,因此n%lcm=n%(k*lcm)%lcm=n%2520%lcm。而n=(...((a5*10+a4)*10+a3)...),根据同余模定理,状态存2520的余数即可,最后在判断能否被lcm整除。

    然而这时f[i][mod][lcm],第二维和第三维长度都是2520,第一维19,显然超内存了,但由于1到9的lcm的所有可能只有48种,离散化即可,因为lcm一定是2520的约数。

    这样就变成了f[i][mod][id]。接着就是f数组不用每次都初始化。。。。。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<vector>
    #include<stack>
    #include<queue>
    #include<set>
    #include<map>
    #include<string>
    #include<math.h>
    #include<cctype>
    #define ll unsigned long long
    #define REP(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
    #define REPP(i,a,b,t) for(int (i)=(a);(i)<=(b);(i)+=(t))
    #define rep(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)
    #define repp(i,a,b,t) for(int (i)=(a);(i)>=(b);(i)-=(t))
    #define PII pair<int,int>
    #define fst first
    #define snd second
    #define MP make_pair
    #define PB push_back
    #define RI(x) scanf("%d",&(x))
    #define RII(x,y) scanf("%d%d",&(x),&(y))
    #define RIII(x,y,z) scanf("%d%d%d",&(x),&(y),&(z))
    #define DRI(x) int (x);scanf("%d",&(x))
    #define DRII(x,y) int (x),(y);scanf("%d%d",&(x),&(y))
    #define DRIII(x,y,z) int (x),(y),(z);scanf("%d%d%d",&(x),&(y),&(z))
    #define RS(x) scanf("%s",x)
    #define RSS(x,y) scanf("%s%s",x,y)
    #define DRS(x) char x[maxn];scanf("%s",x)
    #define DRSS(x,y) char x[maxn],y[maxn];scanf("%s%s",x,y)
    #define MS0(a) memset((a),0,sizeof((a)))
    #define MS1(a) memset((a),-1,sizeof((a)))
    #define MS(a,b) memset((a),(b),sizeof((a)))
    #define ALL(v) v.begin(),v.end()
    #define SZ(v) (int)(v).size()
    
    using namespace std;
    
    const int maxn=1000100;
    const int INF=(1<<29);
    const double EPS=0.0000000001;
    const double Pi=acos(-1.0);
    
    ll L,R;
    int num[30];
    const int MOD=2520;
    ll f[21][2521][50];
    int lcm[50],cnt;
    //map<int,int> ID;
    int ID[2530];
    
    void Init()
    {
        MS0(ID);
        cnt=0;
        REP(i,1,MOD){
            if(MOD%i==0) lcm[cnt++]=i,ID[i]=cnt-1;
        }
    }
    
    ll LCM(ll a,ll b)
    {
        return a/__gcd(a,b)*b;
    }
    
    ll dfs(int i,int mod,int id,bool e)
    {
        if(i==-1) return mod%lcm[id]==0;
        if(!e&&~f[i][mod][id]) return f[i][mod][id];
        ll res=0;
        int u=e?num[i]:9;
        REP(d,0,u){
            if(d==0) res+=dfs(i-1,(mod*10)%MOD,id,e&&d==u);
            else res+=dfs(i-1,(mod*10+d)%MOD,ID[LCM(lcm[id],d)],e&&d==u);
        }
        return e?res:f[i][mod][id]=res;
    }
    
    ll F(ll n)
    {
        MS0(num);
        int len=0;
        while(n){
            num[len++]=n%10;
            n/=10;
        }
        return dfs(len-1,0,ID[1],1);
    }
    
    int main()
    {
        freopen("in.txt","r",stdin);
        Init();
        DRI(T);
        MS1(f);
        while(T--){
            scanf("%I64u%I64u",&L,&R);
            printf("%I64u
    ",F(R)-F(L-1));
        }
        return 0;
    }
    View Code

     G题:

    http://acm.hust.edu.cn/vjudge/contest/view.action?cid=70324#problem/G

    求[0,N]中含有"13"且能被13整除的数的个数。

    有了上一道题的经验,这题直接秒啊。。。竟成水题了。。。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<vector>
    #include<stack>
    #include<queue>
    #include<set>
    #include<map>
    #include<string>
    #include<math.h>
    #include<cctype>
    #define ll long long
    #define REP(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
    #define REPP(i,a,b,t) for(int (i)=(a);(i)<=(b);(i)+=(t))
    #define rep(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)
    #define repp(i,a,b,t) for(int (i)=(a);(i)>=(b);(i)-=(t))
    #define PII pair<int,int>
    #define fst first
    #define snd second
    #define MP make_pair
    #define PB push_back
    #define RI(x) scanf("%d",&(x))
    #define RII(x,y) scanf("%d%d",&(x),&(y))
    #define RIII(x,y,z) scanf("%d%d%d",&(x),&(y),&(z))
    #define DRI(x) int (x);scanf("%d",&(x))
    #define DRII(x,y) int (x),(y);scanf("%d%d",&(x),&(y))
    #define DRIII(x,y,z) int (x),(y),(z);scanf("%d%d%d",&(x),&(y),&(z))
    #define RS(x) scanf("%s",x)
    #define RSS(x,y) scanf("%s%s",x,y)
    #define DRS(x) char x[maxn];scanf("%s",x)
    #define DRSS(x,y) char x[maxn],y[maxn];scanf("%s%s",x,y)
    #define MS0(a) memset((a),0,sizeof((a)))
    #define MS1(a) memset((a),-1,sizeof((a)))
    #define MS(a,b) memset((a),(b),sizeof((a)))
    #define ALL(v) v.begin(),v.end()
    #define SZ(v) (int)(v).size()
    
    using namespace std;
    
    const int maxn=1000100;
    const int INF=(1<<29);
    const double EPS=0.0000000001;
    const double Pi=acos(-1.0);
    
    ll n;
    int num[30];
    ll f[30][12][15][2];
    
    ll dfs(int i,int s,int mod,int has,bool e)
    {
        if(i==-1) return mod==0&&has;
        if(!e&&~f[i][s][mod][has]) return f[i][s][mod][has];
        ll res=0;
        int u=e?num[i]:9;
        REP(d,0,u){
            if(s==1&&d==3) res+=dfs(i-1,d,(mod*10+d)%13,1,e&&d==u);
            else res+=dfs(i-1,d,(mod*10+d)%13,has,e&&d==u);
        }
        return e?res:f[i][s][mod][has]=res;
    }
    
    ll F(ll n)
    {
        MS0(num);
        int len=0;
        while(n){
            num[len++]=n%10;
            n/=10;
        }
        return dfs(len-1,0,0,0,1);
    }
    
    int main()
    {
        freopen("in.txt","r",stdin);
        MS1(f);
        while(cin>>n){
            cout<<F(n)<<endl;
        }
        return 0;
    }
    View Code

     H题:

    http://acm.hust.edu.cn/vjudge/contest/view.action?cid=70324#problem/H

    给定函数F(x)。输入A,B。求[0,B]中的F(x)不超过F(A)的x的个数。

    F(x)的范围是20000左右,f[i][A][sum]这样会超内存,而f[i][sum]则需每次根据A初始化,注意到判断条件是sum<A,因此只需存A-sum即可,这样f就变成f[i][A-sum]。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<vector>
    #include<stack>
    #include<queue>
    #include<set>
    #include<map>
    #include<string>
    #include<math.h>
    #include<cctype>
    #define ll long long
    #define REP(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
    #define REPP(i,a,b,t) for(int (i)=(a);(i)<=(b);(i)+=(t))
    #define rep(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)
    #define repp(i,a,b,t) for(int (i)=(a);(i)>=(b);(i)-=(t))
    #define PII pair<int,int>
    #define fst first
    #define snd second
    #define MP make_pair
    #define PB push_back
    #define RI(x) scanf("%d",&(x))
    #define RII(x,y) scanf("%d%d",&(x),&(y))
    #define RIII(x,y,z) scanf("%d%d%d",&(x),&(y),&(z))
    #define DRI(x) int (x);scanf("%d",&(x))
    #define DRII(x,y) int (x),(y);scanf("%d%d",&(x),&(y))
    #define DRIII(x,y,z) int (x),(y),(z);scanf("%d%d%d",&(x),&(y),&(z))
    #define RS(x) scanf("%s",x)
    #define RSS(x,y) scanf("%s%s",x,y)
    #define DRS(x) char x[maxn];scanf("%s",x)
    #define DRSS(x,y) char x[maxn],y[maxn];scanf("%s%s",x,y)
    #define MS0(a) memset((a),0,sizeof((a)))
    #define MS1(a) memset((a),-1,sizeof((a)))
    #define MS(a,b) memset((a),(b),sizeof((a)))
    #define ALL(v) v.begin(),v.end()
    #define SZ(v) (int)(v).size()
    
    using namespace std;
    
    const int maxn=1000100;
    const int INF=(1<<29);
    const double EPS=0.0000000001;
    const double Pi=acos(-1.0);
    
    ll A,B;
    int num[11];
    ll f[11][21000];
    
    ll dfs(int i,int cha,bool e)
    {
        if(i==-1) return cha>=0;
        if(cha<0) return 0;
        if(!e&&~f[i][cha]) return f[i][cha];
        ll res=0;
        int u=e?num[i]:9;
        REP(d,0,u){
            res+=dfs(i-1,cha-d*(1<<i),e&&d==u);
        }
        return e?res:f[i][cha]=res;
    }
    
    ll F(ll n)
    {
        int len=0;
        while(n){
            num[len++]=n%10;
            n/=10;
        }
        return dfs(len-1,A,1);
    }
    
    ll bin(ll n)
    {
        ll res=0,t=0;
        while(n){
            res+=(n%10)*(1<<t);
            n/=10;t++;
        }
        return res;
    }
    
    int main()
    {
        freopen("in.txt","r",stdin);
        DRI(T);
        int casen=1;
        MS1(f);
        while(T--){
            scanf("%I64d%I64d",&A,&B);
            A=bin(A);
            printf("Case #%d: %I64d
    ",casen++,F(B));
        }
        return 0;
    }
    View Code

     H题:

    http://acm.hust.edu.cn/vjudge/contest/view.action?cid=70324#problem/J

    求[L,R]中的与7无关的数的平方和。

    维护三个数,个数cnt,和sum,平方和sqsum。

    维护cnt和sum的目的是推出sqsum。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<vector>
    #include<stack>
    #include<queue>
    #include<set>
    #include<map>
    #include<string>
    #include<math.h>
    #include<cctype>
    #define ll unsigned long long
    #define REP(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
    #define REPP(i,a,b,t) for(int (i)=(a);(i)<=(b);(i)+=(t))
    #define rep(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)
    #define repp(i,a,b,t) for(int (i)=(a);(i)>=(b);(i)-=(t))
    #define PII pair<int,int>
    #define fst first
    #define snd second
    #define MP make_pair
    #define PB push_back
    #define RI(x) scanf("%d",&(x))
    #define RII(x,y) scanf("%d%d",&(x),&(y))
    #define RIII(x,y,z) scanf("%d%d%d",&(x),&(y),&(z))
    #define DRI(x) int (x);scanf("%d",&(x))
    #define DRII(x,y) int (x),(y);scanf("%d%d",&(x),&(y))
    #define DRIII(x,y,z) int (x),(y),(z);scanf("%d%d%d",&(x),&(y),&(z))
    #define RS(x) scanf("%s",x)
    #define RSS(x,y) scanf("%s%s",x,y)
    #define DRS(x) char x[maxn];scanf("%s",x)
    #define DRSS(x,y) char x[maxn],y[maxn];scanf("%s%s",x,y)
    #define MS0(a) memset((a),0,sizeof((a)))
    #define MS1(a) memset((a),-1,sizeof((a)))
    #define MS(a,b) memset((a),(b),sizeof((a)))
    #define ALL(v) v.begin(),v.end()
    #define SZ(v) (int)(v).size()
    
    using namespace std;
    
    const int maxn=1000100;
    const int INF=(1<<29);
    const double EPS=0.0000000001;
    const double Pi=acos(-1.0);
    
    const ll MOD=1000000000+7;
    ll L,R;
    int num[20];
    struct Node
    {
        ll cnt,sum,sqsum;
    };
    Node f[20][10][10];
    ll p[20];
    
    ll qpow(ll n,ll k,ll p)
    {
        ll res=1;
        while(k){
            if(k&1) res=((res%p)*(n%p))%p;
            n=((n%p)*(n%p))%p;
            k>>=1;
        }
        return res;
    }
    
    Node dfs(int i,int mod1,int mod2,int e)
    {
        if(i==-1){
            if(mod1&&mod2) return {1,0,0};
            return {0,0,0};
        }
        if(!e&&f[i][mod1][mod2].cnt!=-1) return f[i][mod1][mod2];
        Node res={0,0,0};
        int u=e?num[i]:9;
        REP(d,0,u){
            if(d==7) continue;
            Node tmp=dfs(i-1,(mod1+d)%7,(mod2*10+d)%7,e&&d==u);
            res.cnt+=tmp.cnt;
            res.cnt%=MOD;
            res.sum=(res.sum%MOD+tmp.sum%MOD+((tmp.cnt%MOD)*(d*p[i])%MOD)%MOD)%MOD;
            res.sqsum=(res.sqsum%MOD+tmp.sqsum%MOD+(((2*d*p[i])%MOD)*tmp.sum)%MOD+(tmp.cnt%MOD)*qpow(d*p[i],2,MOD))%MOD;
        }
        return e?res:f[i][mod1][mod2]=res;
    }
    
    ll F(ll n)
    {
        int len=0;
        while(n){
            num[len++]=n%10;
            n/=10;
        }
        return dfs(len-1,0,0,1).sqsum%MOD;
    }
    
    void Init()
    {
        MS0(f);
        REP(i,0,19){
            REP(j,0,9){
                REP(k,0,9) f[i][j][k].cnt=-1;
            }
        }
        MS0(p);
        REP(i,0,19){
            p[i]=qpow(10,i,MOD);
        }
    }
    
    int main()
    {
        freopen("in.txt","r",stdin);
        Init();
        DRI(T);
        while(T--){
            cin>>L>>R;
            cout<<(F(R)+MOD-F(L-1))%MOD<<endl;
        }
        return 0;
    }
    View Code

     K题:

    http://acm.hust.edu.cn/vjudge/contest/view.action?cid=70324#problem/K

    求[L,R]中奇数出现偶数次,偶数出现奇数次的数的个数。

    f[i][has][3][3][3][3][3][3][3][3][3][3]:第一维表示位数,has表示是否已经出现了非0位,后面的表示0~9是否出现和出现次数奇偶。

    可以把后面的9维状态按三进制压缩成一个整数,变成一维。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<vector>
    #include<stack>
    #include<queue>
    #include<set>
    #include<map>
    #include<string>
    #include<math.h>
    #include<cctype>
    #define ll unsigned long long
    #define REP(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
    #define REPP(i,a,b,t) for(int (i)=(a);(i)<=(b);(i)+=(t))
    #define rep(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)
    #define repp(i,a,b,t) for(int (i)=(a);(i)>=(b);(i)-=(t))
    #define PII pair<int,int>
    #define fst first
    #define snd second
    #define MP make_pair
    #define PB push_back
    #define RI(x) scanf("%d",&(x))
    #define RII(x,y) scanf("%d%d",&(x),&(y))
    #define RIII(x,y,z) scanf("%d%d%d",&(x),&(y),&(z))
    #define DRI(x) int (x);scanf("%d",&(x))
    #define DRII(x,y) int (x),(y);scanf("%d%d",&(x),&(y))
    #define DRIII(x,y,z) int (x),(y),(z);scanf("%d%d%d",&(x),&(y),&(z))
    #define RS(x) scanf("%s",x)
    #define RSS(x,y) scanf("%s%s",x,y)
    #define DRS(x) char x[maxn];scanf("%s",x)
    #define DRSS(x,y) char x[maxn],y[maxn];scanf("%s%s",x,y)
    #define MS0(a) memset((a),0,sizeof((a)))
    #define MS1(a) memset((a),-1,sizeof((a)))
    #define MS(a,b) memset((a),(b),sizeof((a)))
    #define ALL(v) v.begin(),v.end()
    #define SZ(v) (int)(v).size()
    
    using namespace std;
    
    const int maxn=1000100;
    const int INF=(1<<29);
    const double EPS=0.0000000001;
    const double Pi=acos(-1.0);
    
    ll L,R;
    int num[22];
    ll f[22][2][3][3][3][3][3][3][3][3][3][3];
    
    ll dfs(int i,int has,int t0,int t1,int t2,int t3,int t4,int t5,int t6,int t7,int t8,int t9,bool e)
    {
        int tt[12]={t0,t1,t2,t3,t4,t5,t6,t7,t8,t9};
        if(i==-1){
            REP(k,0,9){
                if(tt[k]!=0&&(tt[k]&1)==(k&1)) return 0;
            }
            return 1;
        }
        if(!e&&~f[i][has][t0][t1][t2][t3][t4][t5][t6][t7][t8][t9]) return f[i][has][t0][t1][t2][t3][t4][t5][t6][t7][t8][t9];
        ll res=0;
        int u=e?num[i]:9;
        int nt=0;
        REP(d,0,u){
            if(d==0){
                if(has){
                    if(t0==0||t0==2) nt=1;
                    else nt=2;
                }
                else nt=0;
                res+=dfs(i-1,has,nt,t1,t2,t3,t4,t5,t6,t7,t8,t9,e&&d==u);
            }
            else{
                int pt=tt[d];
                if(tt[d]==0||tt[d]==2) tt[d]=1;
                else tt[d]=2;
                res+=dfs(i-1,1,tt[0],tt[1],tt[2],tt[3],tt[4],tt[5],tt[6],tt[7],tt[8],tt[9],e&&d==u);
                tt[d]=pt;
            }
        }
        return e?res:f[i][has][t0][t1][t2][t3][t4][t5][t6][t7][t8][t9]=res;
    }
    
    ll F(ll n)
    {
        int len=0;
        while(n){
            num[len++]=n%10;
            n/=10;
        }
        return dfs(len-1,0,0,0,0,0,0,0,0,0,0,0,1);
    }
    
    int main()
    {
        freopen("in.txt","r",stdin);
        DRI(T);
        MS1(f);
        while(T--){
            cin>>L>>R;
            cout<<F(R)-F(L-1)<<endl;
        }
        return 0;
    }
    View Code

     随便找了到水题:

    http://acm.hust.edu.cn/vjudge/contest/view.action?cid=80070#problem/R

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<vector>
    #include<stack>
    #include<queue>
    #include<set>
    #include<map>
    #include<string>
    #include<math.h>
    #include<cctype>
    #define ll long long
    #define REP(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
    #define REPP(i,a,b,t) for(int (i)=(a);(i)<=(b);(i)+=(t))
    #define rep(i,a,b) for(int (i)=(a);(i)>=(b);(i)--)
    #define repp(i,a,b,t) for(int (i)=(a);(i)>=(b);(i)-=(t))
    #define PII pair<int,int>
    #define fst first
    #define snd second
    #define MP make_pair
    #define PB push_back
    #define RI(x) scanf("%d",&(x))
    #define RII(x,y) scanf("%d%d",&(x),&(y))
    #define RIII(x,y,z) scanf("%d%d%d",&(x),&(y),&(z))
    #define DRI(x) int (x);scanf("%d",&(x))
    #define DRII(x,y) int (x),(y);scanf("%d%d",&(x),&(y))
    #define DRIII(x,y,z) int (x),(y),(z);scanf("%d%d%d",&(x),&(y),&(z))
    #define RS(x) scanf("%s",x)
    #define RSS(x,y) scanf("%s%s",x,y)
    #define DRS(x) char x[maxn];scanf("%s",x)
    #define DRSS(x,y) char x[maxn],y[maxn];scanf("%s%s",x,y)
    #define MS0(a) memset((a),0,sizeof((a)))
    #define MS1(a) memset((a),-1,sizeof((a)))
    #define MS(a,b) memset((a),(b),sizeof((a)))
    #define ALL(v) v.begin(),v.end()
    #define SZ(v) (int)(v).size()
    
    using namespace std;
    
    const int maxn=1000100;
    const int INF=(1<<29);
    const double EPS=0.0000000001;
    const double Pi=acos(-1.0);
    
    ll L,R;
    int num[20];
    ll f[20][2][12];
    
    ll dfs(int i,int has,int s,bool e)
    {
        if(i==-1) return 1;
        if(!e&&~f[i][has][s]) return f[i][has][s];
        ll res=0;
        int u=e?num[i]:9;
        REP(d,0,u){
            if(has){
                if(abs(s-d)>=2) res+=dfs(i-1,has,d,e&&d==u);
            }
            else res+=dfs(i-1,d?1:0,d,e&&d==u);
        }
        return e?res:f[i][has][s]=res;
    }
    
    ll F(int n)
    {
        int len=0;
        while(n){
            num[len++]=n%10;
            n/=10;
        }
        return dfs(len-1,0,0,1);
    }
    
    int main()
    {
        freopen("in.txt","r",stdin);
        MS1(f);
        while(cin>>L>>R){
            cout<<F(R)-F(L-1)<<endl;
        }
        return 0;
    }
    View Code

     =====================================================================================================================

    数位dp暂时告一段落了,剩下两道一道要在数位dp上套lis,另一道是AC自动机+数位dp。。。。等学了AC自动机再回来补。

    下一专题:激动人心的线段树!!!

    没有AC不了的题,只有不努力的ACMER!
  • 相关阅读:
    Android 进程生命周期 Process Lifecycle
    .NET Core微服务之基于IdentityServer建立授权与验证服务(续)
    .NET Core微服务之基于IdentityServer建立授权与验证服务
    .NET Core微服务之基于Ocelot实现API网关服务(续)
    .NET Core微服务之基于Ocelot实现API网关服务
    .NET Core微服务之基于Polly+AspectCore实现熔断与降级机制
    .NET Core微服务之基于Consul实现服务治理(续)
    .NET Core微服务之基于Consul实现服务治理
    一朝入梦,终生不醒:再看红楼梦,也谈石头记
    月光下的凤尾竹—彩云之南西双版纳游记
  • 原文地址:https://www.cnblogs.com/--560/p/4690129.html
Copyright © 2011-2022 走看看