A CodeForces 55D Beautiful numbers
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int MAXN = 25;
const int MOD = 2520;//1~9的lcm为2520
long long dp[MAXN][MOD][48];
int index[MOD + 10];//记录1~9的最小公倍数
int bit[MAXN];
int lcm(int a, int b)
{
return a / __gcd(a, b)*b;
}
void init()
{
int num = 0;
for (int i = 1; i <= MOD; i++)
if (MOD%i == 0)
index[i] = num++;
}
long long dfs(int pos, int preSum, int preLcm, bool flag)
{
if (pos == -1)
return preSum%preLcm == 0;
if (!flag && dp[pos][preSum][index[preLcm]] != -1)
return dp[pos][preSum][index[preLcm]];
long long ans = 0;
int end = flag ? bit[pos] : 9;//上界
for (int i = 0; i <= end; i++)
{
int nowSum = (preSum * 10 + i) % MOD;
int nowLcm = preLcm;
if (i)nowLcm = lcm(nowLcm, i);
ans += dfs(pos - 1, nowSum, nowLcm, flag && i == end);
}
if (!flag)
dp[pos][preSum][index[preLcm]] = ans;
return ans;
}
long long calc(long long x)
{
int pos = 0;
while (x)
{
bit[pos++] = x % 10;
x /= 10;
}
return dfs(pos - 1, 0, 1, 1);
}
int main()
{
int T;
long long l, r;
init();
memset(dp, -1, sizeof(dp));
scanf("%d", &T);
while (T--)
{
scanf("%lld%lld", &l, &r);
printf("%lld\n", calc(r) - calc(l - 1));
}
return 0;
}
B HDU 4352 XHXJ's LIS
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
using namespace std;
LL dp[20][1 << 10][11];
int k, bit[20];
int update(int x, int s)
{
for (int i = x; i<10; i++)
{
if (s&(1 << i))
return (s ^ (1 << i)) | (1 << x);
}
return s | (1 << x);
}
int getK(int s)
{
int cnt = 0;
while (s)
{
if (s & 1)cnt++;
s >>= 1;
}
return cnt;
}
LL dfs(int pos, int s, bool e, bool z) //e为上界,z记录前面的是否都为0,1代表全为0
{
if (!pos)
return getK(s) == k;
if (!e && dp[pos][s][k] != -1)
return dp[pos][s][k];
int digit = e ? bit[pos] : 9;
LL ans = 0;
for (int i = 0; i <= digit; i++)
{
ans += dfs(pos - 1, (z && (i == 0)) ? 0 : update(i, s), e&&i == digit, z && (i == 0));
}
if (!e)dp[pos][s][k] = ans;
return ans;
}
LL solve(LL n)
{
int len = 0;
while (n)
{
bit[++len] = n % 10;
n /= 10;
}
return dfs(len, 0, 1, 1);
}
int main()
{
int cas = 1, t;
scanf("%d", &t);
memset(dp, -1, sizeof dp);
while (t--)
{
LL a, b;
cin >> a >> b >> k;
printf("Case #%d: %I64d\n", cas++, solve(b) - solve(a - 1));
}
return 0;
}
HDU 2089 不要62
#include<iostream>
#include<cstdio>
using namespace std;
int dp[10][10];
int d[10];
void init()
{
dp[0][0] = 1;
for (int i = 1; i <= 7; ++i)
for (int j = 0; j <= 9; ++j)
for (int k = 0; k <= 9; ++k)
if (j != 4 && !(j == 6 && k == 2))
dp[i][j] += dp[i - 1][k];
}
int solve(int n)
{
int ans = 0;
int len = 0;
while (n)
{
++len;
d[len] = n % 10;
n /= 10;
}
d[len + 1] = 0;
for (int i = len; i >= 1; --i)
{
for (int j = 0; j < d[i]; ++j)
{
if (d[i + 1] != 6 || j != 2)
ans += dp[i][j];
}
if (d[i] == 4 || (d[i + 1] == 6 && d[i] == 2))
break;
}
return ans;
}
int main()
{
int m, n;
init();
while (scanf("%d%d", &m, &n) == 2)
{
if (n == 0 && m == 0) break;
printf("%d\n", solve(n + 1) - solve(m));
}
return 0;
}
D HDU 3555 Bomb
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef __int64 LL;
LL dp[27][3];
int c[27];
//dp[i][j]:长度为i的数的第j种状态
//dp[i][0]:长度为i但是不包含49的方案数
//dp[i][1]:长度为i且不含49但是以9开头的数字的方案数
//dp[i][2]:长度为i且包含49的方案数
void init()
{
memset(dp, 0, sizeof(dp));
dp[0][0] = 1;
for (int i = 1; i <= 20; i++)
{
dp[i][0] = dp[i - 1][0] * 10 - dp[i - 1][1];//所有情况减去开头为4的情况
dp[i][1] = dp[i - 1][0] * 1;//这个随便
dp[i][2] = dp[i - 1][2] * 10 + dp[i - 1][1];//已经有的随便,有9的就加上4就行
}
}
int cal(LL n)
{
int k = 0;
memset(c, 0, sizeof(c));
while (n)
{
c[++k] = n % 10;
n /= 10;
}
c[k + 1] = 0;
return k;
}
void solve(int len, LL n)
{
int flag = 0; //标记是否出现过49
LL ans = 0;
for (int i = len; i >= 1; i--)
{
ans += c[i] * dp[i - 1][2]; //为什么乘以c[i]因为可以有0~i-1个也就是i个
if (flag) //如果之前出现过49那么直接乘以没有出现49的情况,因为初始时候已经乘以了有49的情况
ans += c[i] * dp[i - 1][0];
else if (c[i] > 4) //这一位前面没有挨着49,但c[i]比4大,那么当这一位填4的时候,要加上dp[i-1][1]
ans += dp[i - 1][1];
if (c[i + 1] == 4 && c[i] == 9)
flag = 1;
}
printf("%I64d\n", ans);
}
int main()
{
int t;
LL n;
init();
scanf("%d", &t);
while (t--)
{
scanf("%I64d", &n);
int len = cal(n + 1);
solve(len, n);
}
return 0;
}
E POJ 3252 Round Numbers
#include<cstdio>
#include<cstring>
int dp[50][50][50], digit[50], s, t;
//dfs间接枚举所有情况
int dfs(int pos, int zero, int one, int lead, int limit)//limit判断上一位数字是否达到上界,lead有没有1出现
{
if (!pos)return zero >= one;
if (!limit&&dp[pos][zero][one] != -1)
return dp[pos][zero][one];
int up = limit ? digit[pos] : 1, ans = 0;
for (int i = 0; i <= up; i++)
ans += dfs(pos - 1, lead ? zero + (i == 0) : 0, one + (i == 1), lead || i == 1, limit&&i == up);
return limit ? ans : dp[pos][zero][one] = ans;
}
int cal(int n)
{
int len = 0;
while (n) digit[++len] = n % 2, n >>= 1;
return dfs(len, 0, 0, 0, 1);
}
int main()
{
memset(dp, -1, sizeof(dp));
scanf("%d%d", &s, &t);
printf("%d\n", cal(t) - cal(s - 1));
}
F HDU 3709 Balanced Number
#include <iostream>
#include<cstdio>
#include<cstring>
using namespace std;
long long dp[30][30][3000];
int num[30];
long long dfs(int pos, int center, int sum, bool flag)
{
if (pos == 0) return sum == 0;
if (sum<0) return 0;
if (!flag&&dp[pos][center][sum] != -1) return dp[pos][center][sum];
long long ans = 0;
int maxn = flag ? num[pos] : 9;
for (int i = 0; i <= maxn; i++)
{
ans += dfs(pos - 1, center, sum + i*(pos - center), i == maxn&&flag);
}
if (!flag) dp[pos][center][sum] = ans;
return ans;
}
long long cal(long long x)
{
long long ans = 0;
int pos = 0;
while (x)
{
num[++pos] = x % 10;
x /= 10;
}
for (int i = 1; i <= pos; i++)
ans += dfs(pos, i, 0, 1);
return ans - pos + 2;
}
int main()
{
int t;
long long n, m;
memset(dp, -1, sizeof(dp));
scanf("%d", &t);
while (t--)
{
scanf("%I64d%I64d", &n, &m);
printf("%I64d\n", cal(m) - cal(n - 1));
}
return 0;
}
G HDU 3652 B - number
#include<iostream>
#include<cstdio>
#include<cstring>
#define mod 13
using namespace std;
int dp[20][15][4];
int num[20];
int dfs(int pos, int mo, int status, bool limit)
{
if (!pos) return status == 2 && mo == 0;
if (!limit&&dp[pos][mo][status] != 0) return dp[pos][mo][status];
int end = limit ? num[pos] : 9;
int sum = 0;
for (int i = 0; i <= end; i++)
{
int a = mo;
int flag = status;
if (flag == 0 && i == 1) flag = 1;
if (flag == 1 && i == 3) flag = 2;
if (flag == 1 && i != 1 && i != 3) flag = 0;
sum += dfs(pos - 1, (a * 10 + i) % mod, flag, limit&&i == end);
}
return limit ? sum : dp[pos][mo][status] = sum;
}
int cal(int n)
{
int pos = 1;
memset(dp, 0, sizeof dp);
while (n>0)
{
num[pos++] = n % 10;
n /= 10;
}
return dfs(pos - 1, 0, 0, true);
}
int main()
{
int n;
while (~scanf("%d", &n))
{
printf("%d\n", cal(n));
}
return 0;
}
H HDU 4734 F(x)
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int digit[20], dp[20][10000], t, a, b, ans, cas = 1;//dp[i][j]表示一共i位的数其中小于j的个数
int dfs(int pos, int st, bool limit)
{
if (pos == 0) return st >= 0;
if (!limit&&dp[pos][st] != -1) return dp[pos][st];
int end = limit ? digit[pos] : 9, ans = 0;
for (int i = 0; i <= end; i++)
ans += dfs(pos - 1, st - i*(1 << (pos - 1)), limit&&i == end);
if (!limit) dp[pos][st] = ans;
return ans;
}
int f(int x)
{
int sum = 0, cnt = 0;
while (x) sum += (x % 10)*(1 << (cnt++)), x /= 10;
return sum;
}
int cal(int a, int b)
{
int cnt = 0;
while (b) digit[++cnt] = b % 10, b /= 10;
return dfs(cnt, f(a), 1);
}
int main()
{
scanf("%d", &t), memset(dp, -1, sizeof(dp));
while (t--) scanf("%d%d", &a, &b), printf("Case #%d: %d\n", cas++, cal(a, b));
}
I HDU 4507 吉哥系列故事――恨7不成妻
/*总状态转移思路
(1) ans.cnt += tmp.cnt
(2) ans.s += tmp.s + [ i*10^p ]*tmp.cnt
(3) ans.ss += tmp.ss + 2*(i*10^p)*tmp.s + [(i*10^p)^2]*tmp.cnt(平方和公式)
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstring>
using namespace std;
typedef long long ll;
const int N = 20;
const int mod = 1e9 + 7;
struct Node
{
ll cnt, s, ss; //与 7 无关的数的个数,与 7 无关的数的和,与 7 无关的数的平方和
Node() { cnt = -1; s = 0, ss = 0; } //默认的构造函数,初始化cnt顺便标记是否访问过
}dp[N + 2][10][10];
ll p[N + 2], dig[N + 2]; //保存10的次方 PS:记得取模,保存数字的每一个数位上的数
void init()
{
p[1] = 1; //因为我的数字的个位用dig[1]表示,所以我用p[1]记录10的0次方
for (int i = 2; i < N; ++i) p[i] = (p[i - 1] * 10) % mod;
}
inline ll EX(ll x) //求平方
{
x %= mod;
return (x*x) % mod;
}
Node dfs(int len, int r1, int r2, bool up)
{
if (len == 0)
{
Node tmp;
tmp.cnt = (r1&&r2); //数位和不是7的倍数且数字不是7的倍数,因为这里已经完成了一组排列,只要判断这里的就行了所以&&
tmp.s = tmp.ss = 0;
return tmp;
}
if (!up&&dp[len][r1][r2].cnt != -1)
return dp[len][r1][r2];
int n = up ? dig[len] : 9;
Node ans; ans.cnt = 0;
for (int i = 0; i <= n; ++i)
{
if (i == 7) continue;
Node tmp = dfs(len - 1, (i + r1) % 7, (i + r2 * 10) % 7, up&&i == n); //得到子状态
ans.cnt = (ans.cnt + tmp.cnt) % mod; //更新个数
ans.s = (ans.s + (tmp.s + (i*p[len]) % mod*tmp.cnt%mod) % mod) % mod; //更新数字
ans.ss = (ans.ss + (tmp.ss + ((2LL * i*p[len] % mod)*tmp.s) % mod) % mod) % mod; //式子太长分开写
ans.ss = (ans.ss + (EX(i*p[len])*tmp.cnt) % mod) % mod;
}
if (!up) dp[len][r1][r2] = ans;
return ans;
}
ll cal(ll x)
{
int len = 0;
while (x)
{
dig[++len] = x % 10;
x /= 10;
}
return dfs(len, 0, 0, 1).ss;
}
int main()
{
init();
int T;
scanf("%d", &T);
while (T--)
{
ll l, r;
scanf("%lld %lld", &l, &r);
printf("%lld\n", ((cal(r) - cal(l - 1)) % mod + mod) % mod);
}
return 0;
}
J SPOJ BALNUM Balanced Numbers
#include <string.h>
#include <stdio.h>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
LL dp[20][60000];
int bit[20];
bool check(int s)
{
int num[10];
for (int i = 0; i<10; i++)
{
num[i] = s % 3;
s /= 3;
}
for (int i = 0; i<10; i++)
{
if (num[i] != 0)
{
if (i % 2 == 0 && num[i] == 2)return false;//偶数数字出现了奇数次,舍去
if (i % 2 == 1 && num[i] == 1)return false;//奇数数字出现了偶数次,舍去
}
}
return true;
}
int getnews(int x, int s)
{
int num[10];
for (int i = 0; i<10; i++)
{
num[i] = s % 3;
s /= 3;
}
if (num[x] == 0)
num[x] = 1;
else
num[x] = 3 - num[x];
int news = 0;
for (int i = 9; i >= 0; i--)
{
news *= 3;
news += num[i];
}
return news;
}
LL dfs(int pos, int s, int flag, int z)
{
if (pos == -1) return check(s);
if (!flag&&dp[pos][s] != -1) return dp[pos][s];
LL ans = 0;
int end = flag ? bit[pos] : 9;
for (int i = 0; i <= end; i++)
ans += dfs(pos - 1, (z&&i == 0) ? 0 : getnews(i, s), flag&&i == end, z&&i == 0);
if (!flag)dp[pos][s] = ans;
return ans;
}
LL solve(LL n)
{
int len = 0;
while (n)
{
bit[len++] = n % 10;
n /= 10;
}
return dfs(len - 1, 0, 1, 1);
}
int main()
{
int T;
memset(dp, -1, sizeof(dp));
LL a, b;
scanf("%d", &T);
while (T--)
{
scanf("%lld%lld", &a, &b);
printf("%lld\n", solve(b) - solve(a - 1));
}
return 0;
}