淘先锋技术网

首页 1 2 3 4 5 6 7

一、题目

问题描述
  将一个数N分为多个正整数之和,即N=a1+a2+a3+…+ak,定义M=a1a2a3*…*ak为N的潜能。
  给定N,求它的潜能M。
  由于M可能过大,只需求M对5218取模的余数。
输入格式
  输入共一行,为一个正整数N。
输出格式
  输出共一行,为N的潜能M对5218取模的余数。
样例输入
10
样例输出
36
数据规模和约定
1<=N<10^18

二、思路

具体思路可见文末参考博客。

先来看几个数找找规律:4=2+2,5=2+3,6=3+3,7=3+2+2,8=3+3+2,9=3+3+3

发现规律如下:

(1)元素不会超过4,因为4=2+2,又可以转化为2的问题,而5=2+3,5<2*3,所以5总能分解成2和3。
(2)尽可能多分解出3,然后分解出2,不要分出1。

考虑任意一个数,除以3之后的结果有以下3种:
(1)能被3除断(即整除),那么就分解为3+3+…+3的情况即可。例如:9=3+3+3。
(2)被3除余1,分解为3+3+…+3+2+2或者3+3+…+3+4的情况,例如:10=3+3+2+2
(3)被3除余2,分解为3+3+…+3+2的情况,例如:11=3+3+3+2。

所以最好是分解成连续的3,或附带一两个2。

那么关键问题就变成了 3的k次方取模 的问题,这个用快速幂可以解决。

具体快速幂可见文末参考视频链接。

三、代码

//正整数N分解使得乘积M最大问题
#include <iostream>
using namespace std;

typedef long long ll;
#define p 5218				//余数

int fastPow(int a,ll k)		//递归实现快速幂
{
	//递归出口
	if (k == 0)
		return 1;
		
	if (k == 1)
		return a;

	ll t = fastPow(a, k / 2) % p;

	if (k % 2 == 0)	//如果k是偶数
		return t * t % p;

	return t * t * a % p;
}
int main()
{
	ll N;
	cin >> N;
	if (N <= 2)
	{
		cout << N;
		return 0;
	}
	
	if (N % 3 == 0)		//如果能够被3直接整除
	{
		ll k = N / 3;	//问题就转化为3的k次方模p
		cout << fastPow(3,k);
		return 0;
	}
	
	if (N % 3 == 1)
	{
		ll k = N / 3 - 1;
		cout << fastPow(3,k) * 4 % p;
		return 0;
	}

	if (N % 3 == 2)
	{
		ll k = N / 3;
		cout << fastPow(3, k) * 2 % p;
		return 0;
	}
}

在这里插入图片描述

四、遇到的问题

在实现快速幂函数时,误将k定义为int类型,导致错误在这里插入图片描述

五、参考

B站
快速幂问题

博客
正整数分解使得乘积最大问题
数论 - 正整数分解使得乘积最大问题