HDU 5179 beautiful number
题意:求一个递减并且上一位是下一位倍数的数,比如931,在 n范围内数的个数。
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
const int N = 15;
int f[N][10]; // 表示i 位数,最高位为j 的数量
void init(){
memset(f, 0, sizeof f);
for(int i=1; i<=9; i++) {
f[1][i] = 1;
}
for(int i=2; i<N; i++){
for(int j=1; j<=9; j++){
for(int k=1; k<=9; k++){
if(j%k == 0){
f[i][j] += f[i-1][k];
}
}
}
}
}
int dp(int n){
if(!n) return 0;
vector<int> nums;
while(n) nums.push_back(n%10), n/=10;
int len = nums.size();
int res = 0;
int last = -1;
// 等于 nums.size() 位的数量
for(int i=nums.size()-1; i>=0; i--){
int x = nums[i];
for(int j=1; j < x; j++){
// last == -1 前面没有数的情况
if(last == -1 || last%j == 0){
res += f[i+1][j];
}
}
if(x == 0 || (last != -1 && last % x)) break;
if(!i && last%x == 0){
res++;
}
last = x;
}
// 小于 nums.size() 位的数量
for(int i=1; i<nums.size(); i++){
for(int j=1; j<=9; j++){
res += f[i][j];
}
}
return res;
}
int main() {
int T, l, r;
cin>>T;
while(T--){
init();
cin>>l>>r;
cout<<dp(r)-dp(l-1)<<endl;
}
return 0;
}
HDU 2089 不要62
地址
杭州人称那些傻乎乎粘嗒嗒的人为62(音:laoer)。
杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来,就可以消除个别的士司机和乘客的心理障碍,更安全地服务大众。
不吉利的数字为所有含有4或62的号码。例如:
62315 73418 88914
都属于不吉利号码。但是,61152虽然含有6和2,但不是62连号,所以不属于不吉利数字之列。
你的任务是,对于每次给出的一个牌照区间号,推断出交管局今次又要实际上给多少辆新的士车上牌照了。
题意:在 n 范围内的数,不包含 4 或者 62 的数字的个数。
#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
const int N = 15;
int f[N][N];
void init(){
for(int i=0; i<=9; i++){
if(i != 4){
f[1][i] = 1;
}
}
for(int i=2; i<N; i++){
for(int j=0; j<=9; j++){
for(int k=0; k<=9; k++){
if(j == 4 || (j == 6 && k == 2)) continue;
f[i][j] += f[i-1][k];
}
}
}
}
int dp(int n){
if(!n) return 1;
vector<int> nums;
while(n) nums.push_back(n%10), n/=10;
int res = 0, last = 0;
for(int i=nums.size()-1; i>=0; i--){
int x = nums[i];
for(int j=0; j<x; j++){
if(j == 4 || (last ==6 && j == 2)) continue;
res += f[i+1][j];
}
if(x == 4 ||(last == 6 && x == 2)) break;
last = x;
if(!i) res++;
}
return res;
}
int main() {
int l, r;
init();
while(cin>>l>>r, l || r){
cout<<dp(r)-dp(l-1)<<endl;
}
return 0;
}
HDU 3555 Bomb
题意:在 n 范围内包含 "49" 的个数,代码是通过 n+1-不包含"49"的个数,包含0。
#include <iostream>
#include <cstring>
#include <vector>
using namespace std;
const int N = 25;
long long f[N][N];
void init(){
memset(f, 0, sizeof f);
for(int i=0; i<=9; i++) f[1][i] = 1;
for(int i=2; i<N; i++){
for(int j=0; j<=9; j++){
for(int k=0; k<=9; k++){
if(j == 4 && k == 9)
continue;
f[i][j] += f[i-1][k];
}
}
}
}
long long dp(long long n){
if(!n) return 1;
vector<int> nums;
while(n) nums.push_back(n%10), n/=10;
long long res = 0, last = 0;
for(int i=nums.size()-1; i>=0; i--){
int x = nums[i];
for(int j=0; j<x; j++){
if(last != 4 || j != 9){
res += f[i+1][j];
}
}
if(last == 4 && x == 9) break;
if(!i) res++;
last = x;
}
return res;
}
int main() {
long long T, n;
cin>>T;
while(T--){
init();
cin>>n;
cout<<n+1-dp(n)<<endl;
}
return 0;
}
UESTC 250 windy数
地址
windy定义了一种windy数。
不含前导零且相邻两个数字之差至少为22的正整数被称为windy数。
windy想知道,在AA和BB之间,包括AA和BB,总共有多少个windy数?
题意:在 l,r 范围内的数字,上一位和下一位数字之差绝对值大于等于2的个数。
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int N = 25;
int f[N][N];
void init(){
for(int i=0; i<=9; i++) f[1][i] = 1;
for(int i=2; i<N; i++){
for(int j=0; j<=9; j++){
for(int k=0; k<=9; k++){
if(abs(j-k) >=2){
f[i][j] += f[i-1][k];
}
}
}
}
}
int dp(int n){
if(!n) return 0;
vector<int> nums;
while(n) nums.push_back(n%10), n/=10;
int res =0, last = -2;
for(int i=nums.size()-1; i>=0; i--){
int x = nums[i];
// 去掉前导零
for(int j=(i == nums.size()-1); j<x; j++){
if(abs(last - j) >= 2){
res += f[i+1][j];
}
}
if(abs(last - x) < 2) break;
if(!i) res++;
last = x;
}
for(int i=1; i<nums.size(); i++){
for(int j=1; j<=9; j++){
res += f[i][j];
}
}
return res;
}
int main()
{
int l, r;
cin>>l>>r;
init();
cout<<dp(r) -dp(l-1)<<endl;
return 0;
}
HDU 3652 B-number
题意:求1~n之间有多少个数字包含13且能被13整除。
#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
//dp[i][j][l][state],i位数j开头1 , (mod) 13的值 l , 是否含有13 (0/1)
int f[12][12][15][2];
int mod(int x, int y){
return (x%y+y)%y;
}
void init() {
memset(f, 0, sizeof f);
for(int i=0;i<10;i++)
f[1][i][i][0] = 1;
int power = 10; // 从2位数开始
for(int i=2;i<=10;i++) {
for(int j=0;j<10;j++) {
for(int k=0;k<10;k++) {
for(int l=0;l<13;l++) {
f[i][j][l][1] += f[i-1][k][mod(l-j*power, 13)][1];
if(j == 1 && k == 3)
f[i][j][l][1] += f[i-1][k][mod(l-j*power, 13)][0];
else
f[i][j][l][0] += f[i-1][k][mod(l-j*power, 13)][0];
}
}
}
power *= 10;
}
}
int dp(int n) {
vector<int> nums;
int power = 1;
while(n){
nums.push_back(n%10), n/=10;
if(n)
power*= 10;
}
int sum = 0;
bool mark = false; // 前面出现过 "13"
int last = 0;
int res = 0;
for(int i = nums.size()-1; i >=0; i--) {
int x = nums[i];
for(int j=0;j<x;j++) {
res += f[i+1][j][mod(-sum, 13)][1]; // 出现过 "13"
if((last == 1 && j == 3) || mark) // 当前为 "13" 或者前面的数出现过 "13"
res += f[i+1][j][mod(-sum, 13)][0];
}
sum += x*power; // 高位数字之和
if(last == 1 && x== 3) // 当前为 "13"
mark = true;
last = x; // 记录上个位置
power /= 10;
}
// 当前数 n 是否包含"13" 并且 mod 13 = 0
if(mark && sum%13 == 0) res++;
return res;
}
int main() {
init();
int n;
while(cin>>n) {
cout<<dp(n)<<endl;
}
return 0;
}