HDU 3652 B-number

題意:

1..n的數中數字包含‘13’且能被13整除的,有多少個。n<10^9

分析:

按位DP

困在能被13整除上了,查了能被13整除的數的特性,不知道怎麼轉化dp...

後來看了解題報告,狀態上多記錄個模13的餘數就好了~


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int ans;
int num[10], ln;
int f[10][13][3];

void NtoNum(int *num, int &ln, int n){
	ln = 0;
	while(n){
		num[++ln] = n % 10;
		n = n / 10;
	}
}

int dfs(int cur, int pre, int mod, bool apr, bool flag){
	int i, ret, high;
	if (cur <= 0)	return apr && mod == 0;
	if (!flag && apr && ~f[cur][mod][2]) return f[cur][mod][2];
	if (!flag && !apr && pre != 1 && ~f[cur][mod][1]) return f[cur][mod][1];
	if (!flag && !apr && pre == 1 && ~f[cur][mod][0]) return f[cur][mod][0];
	
	high = flag ? num[cur] : 9;
	ret = 0;
	for (i = 0; i <= high; i++){
		ret += dfs(cur - 1, i, (mod * 10 + i) % 13, apr || (pre == 1 && i == 3), flag && (i == high));
	}
	if (!flag){
		if (pre == 1 && !apr) f[cur][mod][0] = ret;
		if (pre != 1 && !apr) f[cur][mod][1] = ret;
		if (apr) f[cur][mod][2] = ret;
	}
	return ret;
}

int main(){
	int n;
	while(scanf("%d",&n) != EOF){
		ans = 0;
		NtoNum(num, ln, n);
		memset(f, 0xff, sizeof(f));
		ans = dfs(ln, 0, 0, false, true);
		printf("%d\n", ans);
	}
	return 0;
}

/*
f[i][k][0] 不含13,不以1結尾
f[i][k][1] 不含13,以1結尾
f[i][k][2] 含13

f[i + 1][(k * 10 + num) % 13][0] += f[i][k][0], num != 1
f[i + 1][(k * 10 + 1) % 13][0] += f[i][k][1], num != 1, 3
f[i + 1][(k * 10 + 1) % 13][1] += f[i][k][0] + f[i][k][1]
f[i + 1][(k * 10 + num) % 13][2] += f[i][k][2]
f[i + 1][(k * 10 + 3) % 13][2] += f[i][k][1]
其實又用記憶化搜索實現的。。。1A哦~寫完就A了的哦~哈哈~~
還是記憶化搜索實現簡單。。。
總結經驗,記錄dfs時,不一定要開和參數一樣的數組,
適當變換下,分成幾種情況開多個數組,可以節省下內存
46ms 196k
就是慢點...
*/


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章