Repository navigation
Expand file tree
/
Copy pathp612.cpp
More file actions
103 lines (83 loc) · 2.79 KB
/
Copy pathp612.cpp
File metadata and controls
103 lines (83 loc) · 2.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#include <iostream>
#include <vector>
#include <cstring>
#define MOD 1000267129
using namespace std;
using ll = long long;
ll n;
vector<int> digits;
ll dp[20][2][1024]; // pos, tight, mask
// Extract digits of n into vector
void getDigits(ll x) {
digits.clear();
while (x) {
digits.push_back(x % 10);
x /= 10;
}
reverse(digits.begin(), digits.end());
}
// Digit DP: count how many numbers < n use digits forming 'mask'
ll countDP(int pos, bool tight, int mask) {
if (pos == digits.size()) return mask == 0 ? 0 : 1;
if (dp[pos][tight][mask] != -1) return dp[pos][tight][mask];
int limit = tight ? digits[pos] : 9;
ll res = 0;
for (int d = 0; d <= limit; ++d) {
int new_mask = mask;
if (!(mask == 0 && d == 0)) // skip leading zeros
new_mask |= (1 << d);
res += countDP(pos + 1, tight && (d == limit), new_mask);
}
return dp[pos][tight][mask] = res;
}
// Precompute count[mask] = number of numbers < n with digits forming 'mask'
void computeMaskCounts(vector<ll>& count) {
memset(dp, -1, sizeof(dp));
count.assign(1024, 0);
for (int mask = 1; mask < 1024; ++mask) {
memset(dp, -1, sizeof(dp));
function<ll(int, bool, int)> dfs = [&](int pos, bool tight, int current_mask) -> ll {
if (pos == digits.size()) return (current_mask == mask) ? 1 : 0;
if (dp[pos][tight][current_mask] != -1) return dp[pos][tight][current_mask];
int limit = tight ? digits[pos] : 9;
ll res = 0;
for (int d = 0; d <= limit; ++d) {
int next_mask = current_mask;
if (!(current_mask == 0 && d == 0)) // skip leading zeros
next_mask |= (1 << d);
res += dfs(pos + 1, tight && (d == limit), next_mask);
}
return dp[pos][tight][current_mask] = res;
};
memset(dp, -1, sizeof(dp));
count[mask] = dfs(0, true, 0);
}
}
// Modular inverse of 2 mod MOD
ll modinv2() {
return (MOD + 1) / 2;
}
int main() {
n = 1e18;
getDigits(n);
// Step 1: count how many numbers < n exist for each digit mask
vector<ll> count;
computeMaskCounts(count);
// Step 2: compute total pairs
ll total = ((n - 1) % MOD) * ((n - 2) % MOD) % MOD;
total = total * modinv2() % MOD;
// Step 3: subtract non-friend pairs (disjoint masks)
ll nonFriendPairs = 0;
for (int m1 = 1; m1 < 1024; ++m1) {
for (int m2 = m1 + 1; m2 < 1024; ++m2) {
if ((m1 & m2) == 0) {
ll pairs = count[m1] * count[m2] % MOD;
nonFriendPairs = (nonFriendPairs + pairs) % MOD;
}
}
}
// Final answer
ll result = (total - nonFriendPairs + MOD) % MOD;
cout << result << endl;
return 0;
}