不要62和带4的值
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
int data[20];
ll dp[25][2];
ll dfs(int pos, int h, int sta, bool limit) //limit为临界判断,pos为当前位数(从高到低)其他值根据题意设置
{
if(pos == 0) return 1;
if(!limit && dp[pos][sta]!=-1) return dp[pos][sta]; //一般不变
int up = limit ? data[pos] : 9; //当前位最大值
ll ans = 0;
for(int i = 0; i <= up; i++)
{
if(i==4) continue; //不满足的条件
if(h==6&&i==2) continue;
ans += dfs(pos - 1, i, i==6, i == data[pos] && limit); //递归
}
if(!limit) dp[pos][sta] = ans; //记忆化
return ans;
}
//将每一位存起来
ll solve(ll n)
{
int pos = 0;
while(n)
{
data[++pos] = n % 10;
n /= 10;
}
return dfs(pos , 0, 1, true);
}
int main()
{
ll a, b;
int cnt = 0;
memset(dp, -1, sizeof(dp));
while(~scanf("%lld %lld", &a, &b)&&(a||b))
{
printf("%lld\n", solve(b) - solve(a - 1));
}
return 0;
}
只要带49的数
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
int data[20];
ll dp[25][2][2];
ll dfs(int pos, int h, int sta, bool limit)
{
if(pos == 0)
return h;
if(!limit && dp[pos][h][sta]!=-1)
return dp[pos][h][sta];
int up = limit ? data[pos] : 9;
ll ans = 0;
for(int i = 0; i <= up; i++)
{
if(sta&&i==9)
ans += dfs(pos-1,1,0,i==data[pos]&&limit); //符合条件
else
ans+=dfs(pos-1,h,i==4,i==data[pos]&&limit); //不符合条件
}
if(!limit)
dp[pos][h][sta] = ans;
return ans;
}
ll solve(ll n)
{
int pos = 0;
while(n)
{
data[++pos] = n % 10;
n /= 10;
}
return dfs(pos, 0, 0, true);
}
int main()
{
ll a, n;
scanf("%lld",&n);
int cnt = 0;
memset(dp, -1, sizeof(dp));
while(n--)
{
scanf("%lld", &a);
printf("%lld\n", solve(a));
}
return 0;
}
能被13整除并带13的数字
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
int data[20];
ll dp[25][2][20][10];
ll dfs(int pos, int h,int k, int sta, bool limit) k为当前数取余13的值,又a%mod+b%mod=(a+b)%mod可以验证方法正确
{
if(pos == 0)
return h==1&&k==0;
if(!limit && dp[pos][h][k][sta]!=-1)
return dp[pos][h][k][sta];
int up = limit ? data[pos] : 9;
ll ans = 0;
for(int i = 0; i <= up; i++)
{
if(sta==1&&i==3)
ans+= dfs(pos-1,1,(k*10+i)%13,i,i==data[pos]&&limit); //判断是否含13
else
ans+=dfs(pos-1,h,(k*10+i)%13,i,i==data[pos]&&limit);
}
if(!limit)
dp[pos][h][k][sta] = ans;
return ans;
}
ll solve(ll n)
{
int pos = 0;
while(n)
{
data[++pos] = n % 10;
n /= 10;
}
return dfs(pos, 0, 0,0, true);
}
int main()
{
ll a;
memset(dp, -1, sizeof(dp));
while(~scanf("%lld", &a))
printf("%lld\n", solve(a));
return 0;
}
HDU - 3709 找到平衡支点, 例如4139中以3为支点4*2 + 1*1 = 9 and 9*1 = 9,则该数为我们要找的数。
这题多出来的一步是找平衡支点,遍历查找即可。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
int data[20];
ll dp[25][25][2100];
ll maxx;
ll dfs(int pos, int o,int sta, bool limit)
{
if(pos == 0)
return sta==0;
if(sta<0)
return 0;
if(!limit && dp[pos][o][sta]!=-1)
return dp[pos][o][sta];
int up = limit ? data[pos] : 9;
ll ans = 0;
for(int i = 0; i <= up; i++)
ans+=dfs(pos-1,o,sta+i*(pos-o),i==data[pos]&&limit);
if(!limit)
dp[pos][o][sta] = ans;
return ans;
}
ll solve(ll n)
{
int pos = 0;
ll ans=0;
while(n)
{
data[++pos] = n % 10;
n /= 10;
}
for(int i=1; i<=pos; i++)
ans+=dfs(pos,i,0, 1);
return ans+1-pos; //0000计算了4次,减去pos-1次
}
int main()
{
ll a,n,b;
memset(dp, -1, sizeof(dp));
scanf("%lld",&n);
while(n--)
{
scanf("%lld %lld", &a,&b);
printf("%lld\n",solve(b)-solve(a-1));
}
return 0;
}