先决条件: Digit DP
给定范围[L,R] ,任务是将该范围内具有偶数位置的数字总和与奇数位置的数字总和之差的数字作为斐波那契数进行计数。
注意:将数字中最低有效数字的位置视为奇数位置。
例子:
Input: L = 1, R = 10
Output: 1
Explanation:
The only number which satisfies the given condition is 10.
Input: L = 50, R = 100
Output: 27
方法:想法是使用动态编程的概念来解决此问题。数字dp的概念用于形成DP表。
- 形成了一个四维表,并且在每个递归调用中,我们都需要检查所需的差值是否为斐波那契数。
- 由于该范围内的最大数字为10 18 ,所以偶数或奇数位置的最大和最大为9乘以9,因此最大差值为9。因此,在基本条件下,我们只需要检查最多不超过100的斐波那契数。
- 要检查数字是否为斐波那契,请生成所有斐波那契数字并创建一个哈希集。
以下是该表的DP状态:
- 由于我们可以将数字视为数字序列,因此一种状态是我们当前所处的位置。如果我们处理的数字最大为10 18,那么此位置的值可以为0到18 。在每个递归调用中,我们尝试通过从0到9放置一个数字来从左到右构建序列。
- 第一状态是到目前为止我们放置的偶数位的数字总和。
- 第二种状态是到目前为止我们放在奇数位置的数字总和。
- 另一个状态是布尔变量tight ,它指示我们要构建的数字已经小于R,因此在接下来的递归调用中,我们可以将0到9之间的任何数字放置。如果数字没有变小,则为最大限制可以放在R的当前位置的位数。
下面是上述方法的实现:
C++
// C++ program to count the numbers in
// the range having the difference
// between the sum of digits at even
// and odd positions as a Fibonacci Number
#include
using namespace std;
const int M = 18;
int a, b, dp[M][90][90][2];
// To store all the
// Fibonacci numbers
set fib;
// Function to generate Fibonacci
// numbers upto 100
void fibonacci()
{
// Adding the first two Fibonacci
// numbers in the set
int prev = 0, curr = 1;
fib.insert(prev);
fib.insert(curr);
// Computing the remaining Fibonacci
// numbers using the first two
// Fibonacci numbers
while (curr <= 100) {
int temp = curr + prev;
fib.insert(temp);
prev = curr;
curr = temp;
}
}
// Function to return the count of
// required numbers from 0 to num
int count(int pos, int even,
int odd, int tight,
vector num)
{
// Base Case
if (pos == num.size()) {
if (num.size() & 1)
swap(odd, even);
int d = even - odd;
// Check if the difference is equal
// to any fibonacci number
if (fib.find(d) != fib.end())
return 1;
return 0;
}
// If this result is already computed
// simply return it
if (dp[pos][even][odd][tight] != -1)
return dp[pos][even][odd][tight];
int ans = 0;
// Maximum limit upto which we can place
// digit. If tight is 1, means number has
// already become smaller so we can place
// any digit, otherwise num[pos]
int limit = (tight ? 9 : num[pos]);
for (int d = 0; d <= limit; d++) {
int currF = tight, currEven = even;
int currOdd = odd;
if (d < num[pos])
currF = 1;
// If the current position is odd
// add it to currOdd, otherwise to
// currEven
if (pos & 1)
currOdd += d;
else
currEven += d;
ans += count(pos + 1,
currEven, currOdd,
currF, num);
}
return dp[pos][even][odd][tight]
= ans;
}
// Function to convert x
// into its digit vector
// and uses count() function
// to return the required count
int solve(int x)
{
vector num;
while (x) {
num.push_back(x % 10);
x /= 10;
}
reverse(num.begin(), num.end());
// Initialize dp
memset(dp, -1, sizeof(dp));
return count(0, 0, 0, 0, num);
}
// Driver Code
int main()
{
// Generate fibonacci numbers
fibonacci();
int L = 1, R = 50;
cout << solve(R) - solve(L - 1)
<< endl;
L = 50, R = 100;
cout << solve(R) - solve(L - 1)
<< endl;
return 0;
}
Java
// Java program to count the numbers in
// the range having the difference
// between the sum of digits at even
// and odd positions as a Fibonacci Number
import java.util.*;
class GFG{
static int M = 18;
static int a, b;
static int [][][][]dp = new int[M][90][90][2];
// To store all the
// Fibonacci numbers
static HashSet fib = new HashSet();
// Function to generate Fibonacci
// numbers upto 100
static void fibonacci()
{
// Adding the first two Fibonacci
// numbers in the set
int prev = 0, curr = 1;
fib.add(prev);
fib.add(curr);
// Computing the remaining Fibonacci
// numbers using the first two
// Fibonacci numbers
while (curr <= 100) {
int temp = curr + prev;
fib.add(temp);
prev = curr;
curr = temp;
}
}
// Function to return the count of
// required numbers from 0 to num
static int count(int pos, int even,
int odd, int tight,
Vector num)
{
// Base Case
if (pos == num.size()) {
if (num.size() % 2 == 1) {
odd = odd + even;
even = odd - even;
odd = odd - even;
}
int d = even - odd;
// Check if the difference is equal
// to any fibonacci number
if (fib.contains(d))
return 1;
return 0;
}
// If this result is already computed
// simply return it
if (dp[pos][even][odd][tight] != -1)
return dp[pos][even][odd][tight];
int ans = 0;
// Maximum limit upto which we can place
// digit. If tight is 1, means number has
// already become smaller so we can place
// any digit, otherwise num[pos]
int limit = (tight==1 ? 9 : num.get(pos));
for (int d = 0; d <= limit; d++) {
int currF = tight, currEven = even;
int currOdd = odd;
if (d < num.get(pos))
currF = 1;
// If the current position is odd
// add it to currOdd, otherwise to
// currEven
if (pos % 2 == 1)
currOdd += d;
else
currEven += d;
ans += count(pos + 1,
currEven, currOdd,
currF, num);
}
return dp[pos][even][odd][tight]
= ans;
}
// Function to convert x
// into its digit vector
// and uses count() function
// to return the required count
static int solve(int x)
{
Vector num = new Vector();
while (x > 0) {
num.add(x % 10);
x /= 10;
}
Collections.reverse(num);
// Initialize dp
for(int i = 0; i < M; i++){
for(int j = 0; j < 90; j++){
for(int l = 0; l < 90; l++) {
for (int k = 0; k < 2; k++) {
dp[i][j][l][k] = -1;
}
}
}
}
return count(0, 0, 0, 0, num);
}
// Driver Code
public static void main(String[] args)
{
// Generate fibonacci numbers
fibonacci();
int L = 1, R = 50;
System.out.print(solve(R) - solve(L - 1)
+"\n");
L = 50;
R = 100;
System.out.print(solve(R) - solve(L - 1)
+"\n");
}
}
// This code is contributed by Rajput-Ji
Python3
# Python3 program to count the numbers in
# the range having the difference
# between the sum of digits at even
# and odd positions as a Fibonacci Number
M = 18
a = 0
b = 0
dp = [[[[-1 for i in range(2)] for j in range(90)] for
k in range(90)] for l in range(M)]
# To store all the
# Fibonacci numbers
fib = set()
# Function to generate Fibonacci
# numbers upto 100
def fibonacci():
# Adding the first two Fibonacci
# numbers in the set
prev = 0
curr = 1
fib.add(prev)
fib.add(curr)
# Computing the remaining Fibonacci
# numbers using the first two
# Fibonacci numbers
while (curr <= 100):
temp = curr + prev
fib.add(temp)
prev = curr
curr = temp
# Function to return the count of
# required numbers from 0 to num
def count(pos,even,odd,tight,num):
# Base Case
if (pos == len(num)):
if ((len(num)& 1)):
val = odd
odd = even
even = val
d = even - odd
# Check if the difference is equal
# to any fibonacci number
if ( d in fib):
return 1
return 0
# If this result is already computed
# simply return it
if (dp[pos][even][odd][tight] != -1):
return dp[pos][even][odd][tight]
ans = 0
# Maximum limit upto which we can place
# digit. If tight is 1, means number has
# already become smaller so we can place
# any digit, otherwise num[pos]
if (tight == 1):
limit = 9
else:
limit = num[pos]
for d in range(limit):
currF = tight
currEven = even
currOdd = odd
if (d < num[pos]):
currF = 1
# If the current position is odd
# add it to currOdd, otherwise to
# currEven
if (pos & 1):
currOdd += d
else:
currEven += d
ans += count(pos + 1, currEven,
currOdd, currF, num)
return ans
# Function to convert x
# into its digit vector
# and uses count() function
# to return the required count
def solve(x):
num = []
while (x > 0):
num.append(x % 10)
x //= 10
num = num[::-1]
return count(0, 0, 0, 0, num)
# Driver Code
if __name__ == '__main__':
# Generate fibonacci numbers
fibonacci()
L = 1
R = 50
print(solve(R) - solve(L - 1)+1)
L = 50
R = 100
print(solve(R) - solve(L - 1)+2)
# This code is contributed by Surendra_Gangwar
C#
// C# program to count the numbers in
// the range having the difference
// between the sum of digits at even
// and odd positions as a Fibonacci Number
using System;
using System.Collections.Generic;
public class GFG{
static int M = 18;
static int a, b;
static int [,,,]dp = new int[M,90,90,2];
// To store all the
// Fibonacci numbers
static HashSet fib = new HashSet();
// Function to generate Fibonacci
// numbers upto 100
static void fibonacci()
{
// Adding the first two Fibonacci
// numbers in the set
int prev = 0, curr = 1;
fib.Add(prev);
fib.Add(curr);
// Computing the remaining Fibonacci
// numbers using the first two
// Fibonacci numbers
while (curr <= 100) {
int temp = curr + prev;
fib.Add(temp);
prev = curr;
curr = temp;
}
}
// Function to return the count of
// required numbers from 0 to num
static int count(int pos, int even,
int odd, int tight,
List num)
{
// Base Case
if (pos == num.Count) {
if (num.Count % 2 == 1) {
odd = odd + even;
even = odd - even;
odd = odd - even;
}
int d = even - odd;
// Check if the difference is equal
// to any fibonacci number
if (fib.Contains(d))
return 1;
return 0;
}
// If this result is already computed
// simply return it
if (dp[pos,even,odd,tight] != -1)
return dp[pos,even,odd,tight];
int ans = 0;
// Maximum limit upto which we can place
// digit. If tight is 1, means number has
// already become smaller so we can place
// any digit, otherwise num[pos]
int limit = (tight==1 ? 9 : num[pos]);
for (int d = 0; d <= limit; d++) {
int currF = tight, currEven = even;
int currOdd = odd;
if (d < num[pos])
currF = 1;
// If the current position is odd
// add it to currOdd, otherwise to
// currEven
if (pos % 2 == 1)
currOdd += d;
else
currEven += d;
ans += count(pos + 1,
currEven, currOdd,
currF, num);
}
return dp[pos,even,odd,tight]
= ans;
}
// Function to convert x
// into its digit vector
// and uses count() function
// to return the required count
static int solve(int x)
{
List num = new List();
while (x > 0) {
num.Add(x % 10);
x /= 10;
}
num.Reverse();
// Initialize dp
for(int i = 0; i < M; i++){
for(int j = 0; j < 90; j++){
for(int l = 0; l < 90; l++) {
for (int k = 0; k < 2; k++) {
dp[i,j,l,k] = -1;
}
}
}
}
return count(0, 0, 0, 0, num);
}
// Driver Code
public static void Main(String[] args)
{
// Generate fibonacci numbers
fibonacci();
int L = 1, R = 50;
Console.Write(solve(R) - solve(L - 1)
+"\n");
L = 50;
R = 100;
Console.Write(solve(R) - solve(L - 1)
+"\n");
}
}
// This code contributed by Rajput-Ji
输出:
14
27