BZOJ1799-[Ahoi2009]self 同類分佈
阿新 • • 發佈:2019-02-07
題解:
我們統計前面的模數?
按照平常的思維,會定義為當前掃到前i位,數位和為,數字取模數位和後為,跑一遍的再跑一遍的
然而跑一遍是不行的…因為前面的取模和後面的取模沒有關係,之間是不能轉移的….
那該如何思考?
所以這道題需要列舉數位和(也就是模數),對每個數位和都跑一次,因為數字在範圍內,數位和最大隻會有,是可過的。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll f[21][200][200][2],a,b;
int n,sum=9*18+1,dight[20];
ll find(ll x,int mod)
{
if(!x)return 0;
memset(f,0,sizeof(f));
int num=0;
while(x)
{
dight[++num]=x%10;
x/=10;
}
f[num+1][0][0][0]=1;
for(int i=num+1;i>1;i--)
for(int j=0;j<=mod ;j++)
for(int k=0;k<mod;k++)
{
if(!f[i][j][k][0]&&!f[i][j][k][1])continue;
for(int p=0;p<=9;p++)
{
if(p<dight[i-1]&&(j+p<=mod))f[i-1][j+p][(10*k+p)%mod][1]+=f[i][j][k][0];else
if (p==dight[i-1]&&(j+p<=mod))f[i-1][j+p][(10*k+p)%mod][0]+=f[i][j][k][0];
if(f[i][j][k][1]&&(j+p<=mod)) f[i-1][j+p][(10*k+p)%mod][1]+=f[i][j][k][1];
}
}
return f[1][mod][0][0]+f[1][mod][0][1];
}
int main()
{
scanf("%lld%lld",&a,&b);
ll ans=0;
for(int i=1;i<sum;i++)
ans+=find(b,i)-find(a-1,i);
printf("%lld\n",ans);
return 0;
}