模板
应用范围:[l, r]中满足某种情况的数个数
ll dfs(int pos, int pre, bool limit, bool lead) {
if (pos == -1) return 1;
if (!limit && !lead && dp[pos][...][...] != -1) return dp[pos][...][...];
int End = limit ? a[pos] : 9;
ll ans = 0;
for (int i = 0; i <= End; i++) {
******//操作1
}
if (!limit && !lead) dp[pos][...][...] = ans;
return ans;
}
ll calc(ll x) {
int pos = 0;
while (x) {
a[pos++] = x % 10;
x /= 10;
}
return dfs(pos-1, 0, true, true);
}
基础例题
不要62
#include <bits/stdc++.h>
using namespace std;
//#define ACM_LOCAL
const int N = 2e5 + 10;
const int M = 5e5 + 10;
const int INF = 0x3f3f3f3f;
const double eps = 1e-4;
const int MOD = 1e9 + 7;
typedef long long ll;
typedef pair<int, int> PII;
ll n, m, a[20], dp[20][20];
ll dfs(int pos, int pre, bool limit, bool lead) {
if (pos == -1) return 1;
if (!limit && !lead && dp[pos][pre] != -1) return dp[pos][pre];
int End = limit ? a[pos] : 9;
ll ans = 0;
for (int i = 0; i <= End; i++) {
if (pre == 6) {
if (i != 2 && i != 4) ans += dfs(pos-1, i, limit && i == End, lead && i == 0);
} else {
if (i != 4) ans += dfs(pos-1, i, limit && i == End, lead && i == 0);
}
}
if (!limit && !lead) dp[pos][pre] = ans;
return ans;
}
ll calc(ll x) {
int pos = 0;
while (x) {
a[pos++] = x % 10;
x /= 10;
}
return dfs(pos-1, 0, true, true);
}
void solve(){
memset(dp, -1, sizeof dp);
while (cin >> n >> m) {
if (n == 0 && m == 0) break;
printf("%lld\n", calc(m) - calc(n-1));
}
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
#ifdef ACM_LOCAL
freopen("input", "r", stdin);
freopen("output", "w", stdout);
#endif
solve();
}
windy数
#include <bits/stdc++.h>
using namespace std;
//#define ACM_LOCAL
const int N = 2e5 + 10;
const int M = 5e5 + 10;
const int INF = 0x3f3f3f3f;
const double eps = 1e-4;
const int MOD = 1e9 + 7;
typedef long long ll;
typedef pair<int, int> PII;
ll n, m, a[20], dp[20][20];
ll dfs(int pos, int pre, bool limit, bool lead) {
if (pos == -1) return 1;
if (!limit && !lead && dp[pos][pre] != -1) return dp[pos][pre];
int End = limit ? a[pos] : 9;
ll ans = 0;
for (int i = 0; i <= End; i++) {
if (lead) ans += dfs(pos-1, i, limit && i == End, lead && i == 0);
else {
if (abs(i - pre) >= 2) ans += dfs(pos-1, i, limit && i == End, lead && i == 0);
}
}
if (!limit && !lead) dp[pos][pre] = ans;
return ans;
}
ll calc(ll x) {
int pos = 0;
while (x) {
a[pos++] = x % 10;
x /= 10;
}
return dfs(pos-1, 0, true, true);
}
void solve() {
memset(dp, -1, sizeof dp);
cin >> n >> m;
printf("%lld\n", calc(m) - calc(n - 1));
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
#ifdef ACM_LOCAL
freopen("input", "r", stdin);
freopen("output", "w", stdout);
#endif
solve();
}
手机号码
#include <bits/stdc++.h>
using namespace std;
//#define ACM_LOCAL
const int N = 2e5 + 10;
const int M = 5e5 + 10;
const int INF = 0x3f3f3f3f;
const double eps = 1e-4;
const int MOD = 1e9 + 7;
typedef long long ll;
typedef pair<int, int> PII;
ll n, m, a[20], dp[20][20][20][2][2][2];
ll dfs(int pos, int pre1, int pre2, bool limit, bool lead1, bool lead2, bool eight, bool four, bool flag) {
if (pos == -1) return flag && !(eight && four);
if (!limit && !lead2 && !lead2 && dp[pos][pre1][pre2][eight][four][flag] != -1) return dp[pos][pre1][pre2][eight][four][flag];
int End = limit ? a[pos] : 9;
ll ans = 0;
for (int i = 0; i <= End; i++) {
if (!lead2) {
ans += dfs(pos-1, i, pre1, limit && i == End, lead1 && i == 0, lead1, eight || i == 8, four || i == 4, flag || (i == pre1 && i == pre2 && pre1 == pre2));
} else {
ans += dfs(pos-1, i, pre1, limit && i == End, lead1 && i == 0, lead1, eight || i == 8, four || i == 4, flag);
}
}
if (!limit && !lead1 && !lead2) dp[pos][pre1][pre2][eight][four][flag] = ans;
return ans;
}
ll calc(ll x) {
int pos = 0;
while (x) {
a[pos++] = x % 10;
x /= 10;
}
return dfs(pos-1, 0, 0, true, true, true, false, false, false);
}
void solve() {
memset(dp, -1, sizeof dp);
cin >> n >> m;
printf("%lld\n", calc(m) - calc(n - 1));
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
#ifdef ACM_LOCAL
freopen("input", "r", stdin);
freopen("output", "w", stdout);
#endif
solve();
}
烦人的数学作业
#include <bits/stdc++.h>
using namespace std;
//#define ACM_LOCAL
#define fi first
#define se second
#define il inline
#define re register
const int N = 1e5 + 10;
const int M = 5e5 + 10;
const int INF = 0x3f3f3f3f;
const double eps = 1e-5;
const int MOD = 1e9+7;
typedef long long ll;
typedef pair<int, int> PII;
typedef unsigned long long ull;
ll a[20], dp[20][250];
ll dfs(int pos, bool lead, bool limit, ll sum) {
if (pos == -1) return sum;
if (!limit && !lead && dp[pos][sum] != -1) return dp[pos][sum];
int End = limit ? a[pos] : 9;
ll ans = 0;
for (int i = 0; i <= End; i++) {
ans += dfs(pos-1, lead && i == 0, limit && i == End, sum + i);
ans %= MOD;
}
if (!limit && !lead) dp[pos][sum] = ans;
return ans;
}
ll calc(ll x) {
int pos = 0;
while (x) {
a[pos++] = x % 10;
x /= 10;
}
return dfs(pos-1, true, true, 0);
}
void solve() {
memset(dp, -1, sizeof dp);
int T; cin >> T; while (T--) {
ll n, m; cin >> n >> m;
printf("%lld\n", (calc(m) - calc(n-1) + MOD) % MOD);
}
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
#ifdef ACM_LOCAL
freopen("input", "r", stdin);
freopen("output", "w", stdout);
#endif
solve();
}
诡异数字
#include <bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define re register
typedef long long ll;
typedef pair<int, int> PII;
const int N = 1e5 + 100, M = 1e6 + 5, INF = 0x3f3f3f3f;
const int MOD = 20020219;
ll dp[20][20][20];
int a[20], lim[20];
ll dfs(int pos, int pre, int cnt, bool limit) {
if (pos == -1) return 1;
if (!limit && dp[pos][pre][cnt] != -1) return dp[pos][pre][cnt];
int End = limit ? a[pos] : 9;
ll ans = 0;
for (int i = 0; i <= End; i++) {
if (i == pre) {
if (cnt + 1 <= lim[i]) ans = (ans + dfs(pos-1, i, cnt+1, limit && (i == End))) % MOD;
} else {
if (1 <= lim[i]) ans = (ans + dfs(pos-1, i, 1, limit && (i == End))) % MOD;
}
}
if (!limit) dp[pos][pre][cnt] = ans;
return ans;
}
ll calc(ll x) {
int pos = 0;
if (x < 0) return 0;
while (x) {
a[pos++] = x % 10;
x /= 10;
}
return dfs(pos-1, 0, 0, true);
}
void solve() {
int T; cin >> T; while (T--) {
ll n, m, q; cin >> n >> m >> q;
memset(dp, -1, sizeof dp);
memset(lim, 0x3f, sizeof lim);
for (int i = 1; i <= q; i++) {
int x, y; cin >> x >> y;
lim[x] = min(lim[x], y);
}
cout << (calc(m) - calc(n-1) + MOD) % MOD << endl;
}
}
signed main() {
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
#ifdef ACM_LOCAL
freopen("input", "r", stdin);
freopen("output", "w", stdout);
#endif
solve();
}
进阶例题
萌数
存在回文数只要满足相邻两个相同或间隔一个数相同
#include <bits/stdc++.h>
using namespace std;
//#define ACM_LOCAL
#define fi first
#define se second
#define il inline
#define re register
const int N = 1e5 + 10;
const int M = 5e5 + 10;
const int INF = 0x3f3f3f3f;
const double eps = 1e-5;
const int MOD = 1e9+7;
typedef long long ll;
typedef pair<int, int> PII;
typedef unsigned long long ull;
ll a[1005], dp[1005][20][20][2];
ll dfs(int pos, bool limit, bool lead1, bool lead2, int pre1, int pre2, bool flag) {
if (pos == -1) return flag;
if (!limit && !lead1 && !lead2 && dp[pos][pre1][pre2][flag] != -1) return dp[pos][pre1][pre2][flag];
int End = limit ? a[pos] : 9;
ll ans = 0;
for (int i = 0; i <= End; i++) {
if (!lead2) ans += dfs(pos-1, limit && i == End, lead1 && i == 0, lead1, i, pre1, flag || (i == pre2 || i == pre1));
else if (!lead1) ans += dfs(pos-1, limit && i == End, lead1 && i == 0, lead1, i, pre1, flag || (i == pre1));
else ans += dfs(pos-1, limit && i == End, lead1 && i == 0, lead1, i, pre1, flag);
ans %= MOD;
}
if (!limit && !lead1 && !lead2) dp[pos][pre1][pre2][flag] = ans;
return ans;
}
ll calc(string s) {
for (int i = 0; i < s.size(); i++) a[i] = s[s.size() - i - 1] - '0';
return dfs(s.size()-1, true, true, true, 0, 0, false);
}
bool judge(string s) {
for (int i = 1; i < s.size(); i++) {
if (s[i] == s[i-1]) return true;
else if (i >= 2 && s[i] == s[i-2]) return true;
}
return false;
}
void solve() {
memset(dp, -1, sizeof dp);
string n, m; cin >> n >> m;
printf("%lld\n", (calc(m) - calc(n) + judge(n) + MOD) % MOD);
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
#ifdef ACM_LOCAL
freopen("input", "r", stdin);
freopen("output", "w", stdout);
#endif
solve();
}
[AHOI2009]同类分布
枚举数字和,用dig来存模上数字和之后的值,最后数字和和模数相同而且dig为0说明可以整除原数
#include <bits/stdc++.h>
using namespace std;
//#define ACM_LOCAL
#define fi first
#define se second
#define il inline
#define re register
const int N = 1e5 + 10;
const int M = 5e5 + 10;
const int INF = 0x3f3f3f3f;
const double eps = 1e-5;
const int MOD = 1e9+7;
typedef long long ll;
typedef pair<int, int> PII;
typedef unsigned long long ull;
ll a[1005], dp[20][250][250];
ll dfs(int pos, int dig, bool limit, int sum, int mod) {
if (pos == -1) return (sum == mod && dig == 0);
if (!limit && dp[pos][dig][sum] != -1) return dp[pos][dig][sum];
int End = limit ? a[pos] : 9;
ll ans = 0;
for (int i = 0; i <= End; i++) {
ans += dfs(pos-1, (dig * 10 + i) % mod, limit && i == End, sum + i, mod);
}
if (!limit) dp[pos][dig][sum] = ans;
return ans;
}
ll calc(ll x) {
int pos = 0;
while (x) {
a[pos++] = x % 10;
x /= 10;
}
ll ans = 0;
for (int i = 1; i <= pos*9; i++) {
memset(dp, -1, sizeof dp);
ans += dfs(pos-1, 0, true, 0, i);
}
return ans;
}
void solve() {
ll n, m; cin >> n >> m;
printf("%lld\n", calc(m) - calc(n-1));
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
#ifdef ACM_LOCAL
freopen("input", "r", stdin);
freopen("output", "w", stdout);
#endif
solve();
}
Sum-of-Log
i&j = 0可以推出i和j在二进制相同位上只有一个为1,log2(i+j)+1表示一个数二进制的最高位数,因此枚举最高位找出所有满足i&j=0的个数乘上位数即可
#include <bits/stdc++.h>
using namespace std;
//#define ACM_LOCAL
#define fi first
#define se second
#define il inline
#define re register
const int N = 1e5 + 10;
const int M = 5e5 + 10;
const int INF = 0x3f3f3f3f;
const double eps = 1e-5;
const int MOD = 1e9+7;
typedef long long ll;
typedef pair<int, int> PII;
typedef unsigned long long ull;
ll a[50], b[50], dp[50][2][2];
ll dfs(int pos, bool limit1, bool limit2) {
if (pos == -1) return 1;
if (dp[pos][limit1][limit2] != -1) return dp[pos][limit1][limit2];
int up1 = limit1 ? a[pos] : 1, up2 = limit2 ? b[pos] : 1;
ll ans = 0;
for (int i = 0; i <= up1; i++) {
for (int j = 0; j <= up2; j++) {
if (i && j) continue;
ans += dfs(pos-1, limit1 && i == up1, limit2 && j == up2);
ans %= MOD;
}
}
dp[pos][limit1][limit2] = ans;
return ans;
}
ll calc(ll x, ll y) {
memset(dp, -1, sizeof dp);
memset(a, 0, sizeof a);
memset(b, 0, sizeof b);
int pos1 = 0, pos2 = 0;
while (x) {
a[pos1++] = x % 2;
x /= 2;
}
while (y) {
b[pos2++] = y % 2;
y /= 2;
}
ll ans = 0;
for (int i = 0; i < max(pos1, pos2); i++) {
ll res = 0;
if (i < pos1) res += dfs(i-1, i == pos1-1, i >= pos2);//x的i位为1,y的i位为0
if (i < pos2) res += dfs(i-1, i >= pos1, i == pos2-1);//x的i位为0,y的i位为1
res %= MOD;
ans = (ans + 1ll*(i+1) * res % MOD) % MOD;
}
return ans;
}
void solve() {
int T; cin >> T; while (T--) {
ll n, m; cin >> n >> m;
printf("%lld\n", calc(n, m));
}
}
signed main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
#ifdef ACM_LOCAL
freopen("input", "r", stdin);
freopen("output", "w", stdout);
#endif
solve();
}