先决条件:数字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,因此最大差值。因此,我们只需要在基本条件下检查最多 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
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。