51nod-1201 Integer division

Baseline Time Limit: 1 second Space Limit: 131072 KB Score: 80  Difficulty: Level 5 Algorithm Questions
 collect
 focus on
Divide N into the sum of several different integers, how many different division methods are there, for example: n = 6, {6}{1,5}{2,4}{1,2,3}, a total of 4 kinds. Since the data is large, the result of Mod 10^9 + 7 can be output.
Input
Enter 1 number N (1 <= N <= 50000).
Output
The number of output divisions Mod 10^9 + 7.
Input example
6
Output example
4

Problem solution: Let dp[j][i] be the scheme that takes the first j numbers and the sum is i. To reach dp[j][i], there are two options:

The first scheme does not add new elements, that is, from dp[j][x] to dp[j][i], in order to ensure non-repetition, each element is +1, that is, x = i - j;

The second scheme adds new elements, that is, from dp[j - 1][x] to dp[j][i], in order to ensure that dp[j - 1][x] and dp[j][x] do not repeat, We found that the elements of dp[j][x] are all larger by 1, so the new element of dp[j - 1][x] is 1, that is, x = i - j;

So the transition equation is: dp[j][i] = dp[j][i - j] + dp[j - 1][i - j]. The time and space complexity of this method is O(n^2), and the timeout exceeds the memory!

Divide n numbers into two parts [0, (sqrt(n) + 0.9)),[(sqrt(n) + 0.9), n];

For the first part use 01 back. Time is O(n * (sqrt(n) + 0.9));

For the second part, each element is taken at most (sqrt(n) + 0.9) times, we define the first one to take j elements, so we can use the transition equation: dp[j][i] = dp[j] [i - j] + dp[j - 1][i - j]; Note that because the new element is not 1 but (sqrt(n) + 0.9), it is necessary to change the transfer equation,

The final equation is: dp[j][i] = dp[j][i - j] + dp[j - 1][i - j - (sqrt(n) + 0.9) + 1]; the complexity is also O(n * (sqrt(n) + 0.9)); record a f1 array,

f1[i] = ∑(1<=x<=(sqrt(n) + 0.9))dp[x][i];

Finally ride it up!

AC code

#include <stdio.h>
#include <iostream>
#include <string>
#include <queue>
#include <map>
#include <vector>
#include <algorithm>
#include <string.h>
#include <cmath>
typedef long long ll;
 
using namespace std;

const ll maxn = 55555, mod = 1e9 + 7;
ll dp[244][maxn] = {0}, f[maxn] = {0}, f1[maxn] = {0};

int main(){
	ll n;
	scanf("%lld", &n);
	ll m = int(double(sqrt(n) + 0.9));
	f[0] = f1[0] = 1;
	for(ll i = 1; i < m; i++){
		for(ll j = n; j - i >= 0; j--)
			f[j] = (f[j] + f[j - i]) % mod;
	}
	dp[1][m] = 1;
	for(ll i = m; i <= n; i++){
		for(ll j = 1; j <= m; j++){
			dp[j][i] = (dp[j][i - j] + dp[j][i]) % mod;
			if(i - m - j + 1 >= 0)
				dp[j][i] = (dp[j][i] + dp[j - 1][i - m - j + 1]) % mod;
			f1[i] = (f1[i] + dp[j][i]) % mod;
		}
	}
	ll ans = 0;
	for(ll i = 0; i <= n; i++)
		ans = (ans + f1 [i] * f [n - i])% mod;
	printf("%lld\n", ans);
	return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325939115&siteId=291194637