Skip to content

Commit 7d462c8

Browse files
Add files via upload
1 parent a725cbe commit 7d462c8

File tree

1 file changed

+220
-0
lines changed

1 file changed

+220
-0
lines changed
Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
#include <iostream>
2+
#include <vector>
3+
using namespace std;
4+
5+
const int MAX_LENGTH = 1001, MOD = 1e9 + 7;
6+
vector <long long> factorial(MAX_LENGTH), inverse_factorial(MAX_LENGTH);
7+
vector <int> lucky;
8+
9+
long long power(long long x, long long p, long long mod)
10+
{
11+
long long answer = 1;
12+
13+
while(p > 0)
14+
{
15+
if(p%2 == 1)
16+
{
17+
answer = (answer*x)%mod;
18+
}
19+
20+
x = (x*x)%mod;
21+
p = p >> 1;
22+
}
23+
24+
return answer;
25+
}
26+
27+
28+
void precompute_lucky()
29+
{
30+
lucky.push_back(4);
31+
lucky.push_back(7);
32+
33+
for(int current_level_beginning = 0; lucky.back()*10 < MAX_LENGTH;)
34+
{
35+
int current_size = lucky.size();
36+
37+
for(int i = current_level_beginning; i < current_size; i++)
38+
{
39+
lucky.push_back(lucky[i]*10 + 4);
40+
lucky.push_back(lucky[i]*10 + 7);
41+
}
42+
43+
current_level_beginning = current_size;
44+
}
45+
}
46+
47+
void precompute_factorial()
48+
{
49+
factorial[0] = 1;
50+
for(int i = 1; i < MAX_LENGTH; i++)
51+
{
52+
factorial[i] = (factorial[i - 1]*i)%MOD;
53+
}
54+
55+
//i*(i - 1)! = i!
56+
inverse_factorial[MAX_LENGTH - 1] = power(factorial[MAX_LENGTH - 1], MOD - 2, MOD);
57+
for(int i = MAX_LENGTH - 2; i >= 0; i--)
58+
{
59+
inverse_factorial[i] = inverse_factorial[i + 1]*(i + 1);
60+
inverse_factorial[i] %= MOD;
61+
}
62+
}
63+
64+
long long choose(long long n, long long r)
65+
{
66+
long long numerator = factorial[n];
67+
long long inverse_denominator = inverse_factorial[n - r]*inverse_factorial[r];
68+
inverse_denominator %= MOD;
69+
70+
return (numerator*inverse_denominator)%MOD;
71+
}
72+
73+
int is_lucky_digit(int d)
74+
{
75+
return ( (d == 4) || (d == 7) );
76+
}
77+
78+
79+
long long get_lucky(string N)
80+
{
81+
const int MOD = 1e9 + 7;
82+
long long lucky_count = 0;
83+
84+
const int NO_OF_DIGITS = 10;
85+
vector <int> prefix_frequency(NO_OF_DIGITS);
86+
87+
for(int i = 0; i < N.size(); i++)
88+
{
89+
int remaining_digits = (N.size() - 1) - i;
90+
for(int current_digit = 0; current_digit < N[i] - '0'; current_digit++)
91+
{
92+
if(i == 0 && current_digit == 0)
93+
{
94+
continue;
95+
}
96+
for(auto lucky_frequency : lucky)
97+
{
98+
int lucky_prefix_frequency =
99+
prefix_frequency[4] + prefix_frequency[7]
100+
+ (current_digit == 4 || current_digit == 7);
101+
102+
if(lucky_frequency < lucky_prefix_frequency ||
103+
lucky_frequency > lucky_prefix_frequency + remaining_digits)
104+
{
105+
continue;
106+
}
107+
108+
int frequency_4 = prefix_frequency[4] + (current_digit == 4);
109+
int frequency_7 = prefix_frequency[7] + (current_digit == 7);
110+
111+
int lucky_suffix = lucky_frequency - frequency_4 - frequency_7;
112+
113+
long long choosing_lucky_suffix = choose(remaining_digits, lucky_suffix);
114+
choosing_lucky_suffix *= power(2, lucky_suffix, MOD);
115+
choosing_lucky_suffix %= MOD;
116+
117+
int non_lucky_suffix = remaining_digits - lucky_suffix;
118+
long long choosing_non_lucky_suffix = power(8, non_lucky_suffix, MOD);
119+
120+
long long count_here = choosing_lucky_suffix*choosing_non_lucky_suffix;
121+
count_here %= MOD;
122+
123+
lucky_count += count_here;
124+
lucky_count %= MOD;
125+
126+
//cout << "N = " << N << " i = " << i << " d = " << current_digit << " Lucky " << lucky_frequency << "\nLucky Count = " << choosing_lucky_suffix << " others = " << choosing_non_lucky_suffix << " count = " << count_here << "\n";
127+
}
128+
}
129+
130+
prefix_frequency[N[i] - '0']++;
131+
}
132+
133+
for(int i = 1; i < N.size(); i++)
134+
{
135+
for(int d = 1; d <= 9; d++)
136+
{
137+
int remaining_digits = (N.size() - 1) - i;
138+
for(auto lucky_frequency : lucky)
139+
{
140+
int lucky_here = (d == 4 || d == 7);
141+
if(lucky_frequency > lucky_here + remaining_digits)
142+
{
143+
continue;
144+
}
145+
146+
int lucky_suffix_leading_0 = lucky_frequency - (d == 4 || d == 7);
147+
148+
long long choosing_lucky_suffix_leading_0 = choose(remaining_digits, lucky_suffix_leading_0);
149+
choosing_lucky_suffix_leading_0 *= power(2, lucky_suffix_leading_0, MOD);
150+
choosing_lucky_suffix_leading_0 %= MOD;
151+
152+
int non_lucky_suffix_leading_0 = remaining_digits - lucky_suffix_leading_0;
153+
long long choosing_non_lucky_suffix_leading_0 = power(8, non_lucky_suffix_leading_0, MOD);
154+
155+
long long count_here_leading_0 = choosing_lucky_suffix_leading_0*choosing_non_lucky_suffix_leading_0;
156+
count_here_leading_0 %= MOD;
157+
158+
lucky_count += count_here_leading_0;
159+
lucky_count %= MOD;
160+
161+
//cout << "N0 = " << N << " i = " << i << " d = " << d << " Lucky " << lucky_frequency << "\nLucky Count = " << choosing_lucky_suffix_leading_0 << " others = " << choosing_non_lucky_suffix_leading_0 << " count = " << count_here_leading_0 << "\n";
162+
}
163+
}
164+
}
165+
166+
return lucky_count;
167+
}
168+
169+
string add_1(string N)
170+
{
171+
for(int i = N.size() - 1; i >= 0; i--)
172+
{
173+
if(N[i] != '9')
174+
{
175+
N[i]++;
176+
break;
177+
}
178+
else
179+
{
180+
N[i] = '0';
181+
}
182+
}
183+
184+
if(N[0] == '0')
185+
{
186+
N = "1" + N;
187+
}
188+
189+
return N;
190+
}
191+
192+
void solve()
193+
{
194+
string left, right;
195+
cin >> left >> right;
196+
197+
string right_plus_1 = add_1(right);
198+
//cout << "R = " << right_plus_1 << "\n";
199+
200+
const int MOD = 1e9 + 7;
201+
long long answer = get_lucky(right_plus_1) - get_lucky(left) + MOD;
202+
answer %= MOD;
203+
204+
//cout << "Answer = " << answer << "\n";
205+
cout << answer << "\n";
206+
}
207+
208+
int main()
209+
{
210+
precompute_lucky();
211+
precompute_factorial();
212+
213+
int no_of_test_cases;
214+
cin >> no_of_test_cases;
215+
216+
while(no_of_test_cases--)
217+
solve();
218+
219+
return 0;
220+
}

0 commit comments

Comments
 (0)