A. 不包含 x 的数
时间限制:1000 ms内存限制:256 MB类型:传统评测:文本比较上传者: sysulby
题目描述
统计 范围内,不包含数字 x的数有多少个。
输入格式
输入只有一行三个整数l , r, x。
输出格式
输出一行,一个整数sum,表示满足条件的数的个数。
样例
样例输入复制
1 100 1
样例输出复制
80
AC代码
#include<bits/stdc++.h>
using namespace std;
int x;
long long dgt[20],n,dp[20][2];
long long dfs(int i,int o){
if(dp[i][o] != -1)return dp[i][o];
long long ret = 0;
if(i == 0)return 1;
int k = (o ? dgt[i]: 9);
for(int d = 0;d <= k;d++){
if(d == x)continue;
ret += dfs(i-1,o && d == k);
}
dp[i][o] = ret;
return ret;
}
long long calc(long long num){
n = 0;
while(num){
n++;
dgt[n] = num % 10;
num = num/10;
}
memset(dp,-1,sizeof(dp));
return dfs(n,1);
}
int main(){
long long l,r;
cin>>l>>r>>x;
cout<<calc(r)-calc(l-1);
}
B. 不包含 xx 的数
限制:256 MB类型:传统评测:文本比较上传者: sysulby
题目描述
统计 范围内,不包含两位数 的数有多少个。
输入格式
输入只有一行三个整数 , , 。
输出格式
输出一行,一个整数,表示满足条件的数的个数。
样例
样例输入复制
1 1000 10
样例输出复制
979
核心思路
在dfs前记录上一位是多少。
如果是目标数则continue;
AC代码
#include<bits/stdc++.h>
using namespace std;
int x;
long long dgt[20],n,dp[20][10][2];
long long dfs(int i,int j,int o){
if(dp[i][j][o] != -1)return dp[i][j][o];
long long ret = 0;
if(i == 0)return 1;
int k = (o ? dgt[i]: 9);
for(int d = 0;d <= k;d++){
if(j*10+d == x)continue;
ret += dfs(i-1,d,o && d == k);
}
dp[i][j][o] = ret;
return ret;
}
long long calc(long long num){
n = 0;
while(num){
n++;
dgt[n] = num % 10;
num = num/10;
}
memset(dp,-1,sizeof(dp));
return dfs(n,0,1);
}
int main(){
long long l,r;
cin>>l>>r>>x;
cout<<calc(r)-calc(l-1);
}
C. 与 x 无关的数
时间限制:1000 ms内存限制:256 MB类型:传统评测:文本比较上传者: sysulby
题目描述
统计 范围内,有多少个数与数字 无关。
即数位中既不包含 ,这个数本身也不是 的倍数。
输入格式
输入只有一行三个整数 , , 。
输出格式
输出一行,一个整数,表示满足条件的数的个数。
样例
样例输入复制
1 100 7
样例输出复制
70
核心思路
定义 j 表示,余数,和前面状压博客上的一道题差不多,只要余数不为0就好,不需要知道前面怎么排列。
AC代码
#include<bits/stdc++.h>
using namespace std;
int x;
long long dgt[20],n,dp[20][10][2];
long long dfs(int i,int j,int o){//求第i位状态为o的可能
if(dp[i][j][o] != -1)return dp[i][j][o];
long long ret = 0;
if(i == 0)return j != 0;
int k = (o ? dgt[i]: 9);
for(int d = 0;d <= k;d++){
if(d == x)continue;
ret += dfs(i-1,(j*10+d)% x,o && d == k);
}
dp[i][j][o] = ret;
return ret;
}
long long calc(long long num){
n = 0;
while(num){
n++;
dgt[n] = num % 10;
num = num/10;
}
memset(dp,-1,sizeof(dp));
return dfs(n,0,1);
}
int main(){
long long l,r;
cin>>l>>r>>x;
cout<<calc(r)-calc(l-1);
}
D. 数字计数
时间限制:1000 ms内存限制:512 MB类型:传统评测:文本比较上传者: sysulby
题目描述
原题来自:ZJOI 2010
给定两个正整数 和 ,求在 中的所有整数中,每个数码 (digit) 各出现了多少次。
输入格式
仅包含一行两个整数 ,含义如上所述。
输出格式
包含一行 个整数,分别表示 在 中出现了多少次。
样例
样例输入复制
1 99
样例输出复制
9 20 20 20 20 20 20 20 20 20
AC代码
#include<bits/stdc++.h>
using namespace std;
int x;
long long dgt[20],n,dp[20][2][2];
long long dfs(int i,int o,int z){
if(dp[i][o][z] != -1)return dp[i][o][z];
long long ret = 0;
if(i == 0)return 0;
int k = (o ? dgt[i]: 9);
for(int d = 0;d <= k;d++){
ret+= dfs(i-1,o&& d == k,z && d == 0);
if(d == x){
if(z&&d == 0)continue;
if(o && d == k){
long long tmp = 0;
for(int j = i-1;j >= 1;j--)tmp = tmp*10+dgt[j];
ret += tmp+1;
}
else{
long long tmp = 1;
for(int j = i-1;j >= 1;j--)tmp = tmp*10;
ret += tmp;
}
}
}
dp[i][o][z] = ret;
return ret;
}
long long calc(long long num){
n = 0;
while(num){
n++;
dgt[n] = num % 10;
num = num/10;
}
memset(dp,-1,sizeof(dp));
return dfs(n,1,1);
}
int main(){
long long l,r;
cin>>l>>r;
for(;x <= 9;x++)cout<<calc(r)-calc(l-1)<<" ";
}
E. windy数
时间限制:1000 ms内存限制:512 MB类型:传统评测:文本比较上传者: sysulby
题目描述
原题来自:SCOI 2009
windy定义了一种windy数。不含前导零且相邻两个数字之差至少为2的正整数被称为windy数。 windy想知道,在A和B之间,包括A和B,总共有多少个windy数?
输入格式
包含两个整数,A B。
输出格式
一个整数
样例
input1复制
1 10
input2复制
25 50
output1复制
9
output2复制
20
核心思路
记录上一位是多少,并判断是否为前导0。
若这位选择的是小于2,则continue
AC代码
#include<bits/stdc++.h>
using namespace std;
int x;
long long dgt[20],n,dp[20][2][2][10];
long long dfs(int i,int o,int z,int j){
if(dp[i][o][z][j] != -1)return dp[i][o][z][j];
long long ret = 0;
if(i == 0)return 1;
int k = (o ? dgt[i]: 9);
for(int d = 0;d <= k;d++){
if(z == 0 &&abs(d-j) < 2)continue;
ret+= dfs(i-1,o&& d == k,z && d == 0,d);
}
dp[i][o][z][j] = ret;
return ret;
}
long long calc(long long num){
n = 0;
while(num){
n++;
dgt[n] = num % 10;
num = num/10;
}
memset(dp,-1,sizeof(dp));
return dfs(n,1,1,0);
}
int main(){
long long l,r;
cin>>l>>r;
cout<<calc(r)-calc(l-1);
}
F. 同类分布
时间限制:3000 ms内存限制:256 MB类型:传统评测:文本比较上传者: sysulby
题目描述
原题来自:AHOI 2009
给出两个数 ,求出 [a,b]中各位数字之和能整除原数的数的个数。
输入格式
一行,两个整数 a和 b。
输出格式
一个整数sum,表示答案。
样例
样例输入复制
10 19
样例输出复制
3
核心思路
提前枚举模数,若数位和与模数一致则是正确的数。
AC代码
#include<bits/stdc++.h>
using namespace std;
int x,T;
long long dgt[20],n,dp[20][2][200][200];
long long dfs(int i,int o,int sum,int pd){
if(dp[i][o][sum][pd] != -1)return dp[i][o][sum][pd];
long long ret = 0;
if(i == 0&&sum==T&&pd == 0)return 1;
if(i == 0)return 0;
int k = (o ? dgt[i]: 9);
for(int d = 0;d <= k;d++){
ret += dfs(i-1,o && d == k,sum+d,(pd*10+d)%T);
}
dp[i][o][sum][pd] = ret;
return ret;
}
long long calc(long long num){
n = 0;
long long ans = 0;
while(num){
n++;
dgt[n] = num % 10;
num = num/10;
}
for(T = 1;T <= n*9;T++){
memset(dp,-1,sizeof(dp));
ans += dfs(n,1,0,0);
}
return ans;
}
int main(){
long long l,r;
cin>>l>>r;
cout<<calc(r)-calc(l-1);
}