BZOJ1799: [Ahoi2009]self 同类分布

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1799

数位dp。。

f[i][o][k]表示当前第i位,模数为o,和为k。

然后转移就是f[i+1][o*10+j][k+j]+=f[i][o][k](j+k<=o)

然后枚举模数o统计。。。

注意符合条件的是取模后为0,加起来为o 。。

(跑得巨慢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 bin[20];
ll f[19][175][175];
ll a,b,ans;
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){
    int ans=0;
    while (x){ x/=10; ans++;}
    return ans;
}
ll cal(ll x,int o){
    int a;
    int tmp1=0,tmp2=0;
    int l=get(x);
      ll ans=0;
    while (l){
        a=x/bin[l-1];
        rep(i,0,a-1) if (o-tmp2-i>=0) ans+=f[l-1][(o-(1LL*tmp1+1LL*i*bin[l-1]%o)%o)%o][o-tmp2-i]; else break;
        tmp2=tmp2+a;
        tmp1=(1LL*tmp1+1LL*a*bin[l-1])%o;  
        x%=bin[l-1];
        l--; 
    }
    a=x; 
    if ((tmp1+a)%o==0&&tmp2+a==o) ans++;
    return ans;
}
int main(){
    bin[0]=1; rep(i,1,18) bin[i]=bin[i-1]*10;
    a=read(); b=read();
    if (b==bin[18]) b--,ans++;
    int l=get(b);
    rep(o,1,l*9){
        rep(i,0,l) rep(x,0,o) rep(k,0,o) f[i][x][k]=0;
        f[0][0][0]=1; 
        rep(i,0,l-1) rep(x,0,o-1) rep(k,0,o) if (f[i][x][k]) {
            rep(j,0,9) if (j+k<=o) f[i+1][(x*10+j)%o][j+k]+=f[i][x][k];
        } 
        ans+=cal(b,o)-cal(a-1,o);   
    }
     
    printf("%lld\n",ans);
    return 0;
} 

 

posted on 2016-01-13 13:13  ctlchild  阅读(621)  评论(0编辑  收藏  举报

导航