您的位置:首页 > 其它

HDOJ 5976 Detachment【2016大连现场】【数学好题】

2016-11-07 12:41 423 查看
题意很简单:将一个整数n分解成很多不相同整数的和,使得这些整数乘积尽可能大。其中n最大1e9

第一眼看到这个题:

好简单啊,都分解成3啊!(没看到不相同)

第二眼:

可以猜想几个结论:

A:首先不可能有1,不要当作废话,那么意味着从2开始分解是有可能的

B:分解成尽可能多的数。个数多,比数大要好

举个例子:5=2+3,但是5如果不分解,答案是5;但是分解之后,5=2+3,答案为2*3=6

由这两个看似有道理的情况,说明我们要从2开始,不断往上加,来构造n:即:2+3+4+5+……

可惜的是:没有这么幸福的事,因为不相同,所以会有重复

比如7:7=2+3+2,剩下的这个2,怎么办:分解成1+1,往2+3上面分配就好:7=3+4

比如8:8=2+3+3,剩下的这个3,怎么办:分解成1+2,往2+3上面分配就好:8=3+5

所以,按照这个方法,我们猜想得到:这个题是一个构造题

为了方便自己计算,也为了方便最后编程之后得到更快的检验,我们先手算把简单的数字都算出来:

1=1

2=2

3=3

4=4

5=2+3

6=2+3+1=2+4

7=2+3+2=3+4

8=2+3+3=2+3+1+2=3+5

9=2+3+4

10=2+3+4+1=2+3+5

11=2+3+4+2=2+3+4+1+1=2+4+5

12=2+3+4+3=2+3+4+1+1+1=3+4+5

13=2+3+4+4=2+3+4+1+1+2=3+4+6

14=2+3+4+5

15=2+3+4+5+1=2+3+4+6

可以看到:分解数的个数是非递减的

意思是:我们可以根据输入的n,求出构造n的数位的长度len是多少

考虑到1+2+……+len是有公式的,我们可以算几个得到len

得到len之后,我们需要知道在1到len中少了哪几个数,多了哪几个外面的数

发现了几个规律:

当数字刚好是:2+3+……(len+1)的时候,刚好答案是(len+1)!

如果不是上面那种情况:那么只有两种情况:

A:缺1个数,可能缺2,3,4,等某一个

B:缺2个数,必然缺2,而且另一个是len

所以,我们把这些在的值乘起来就好

但是,这个题时限卡得很死

所以要用数学办法预处理好阶乘和逆元来搞

当答案跟len有关的时候,我们直接使用len的阶乘值

当要删去某个值的时候,我们直接乘那个数的逆元就好

代码如下:

#include<bits/stdc++.h>
using namespace std;

#define LL __int64
int t;
LL jiecheng[100050];
LL niyuan[100050];
LL x,mod=1e9+7;

LL qp(LL x,LL p){
if (p==1) return x;
LL res=1;
while(p){
if (p%2) res=(res*x)%mod;
p/=2;
x=x*x%mod;
}
return res;
}

int main(){
//freopen("input.txt","r",stdin);
jiecheng[1]=1;
for(int i=2;i<=100000;i++)
jiecheng[i]=(jiecheng[i-1]*i)%mod;
for(int i=2;i<=100000;i++)
niyuan[i]=qp(1LL*i,mod-2);
scanf("%d",&t);
for(int Case=1;Case<=t;Case++){
scanf("%I64d",&x);
LL len,sum;
if (x<=4){
printf("%I64d\n",x);
continue;
}
else if (x==5){
puts("6");
continue;
}
//printf("%I64d: ",x);
len=(long long)(sqrt(2.0*x));
while((1+len+1)*(1+len)>2*(1+x)) len--;
//printf("%I64d %I64d\n",x,len);
len++;
sum=(1+len)*len/2;
if (sum==x+1) printf("%I64d\n",jiecheng[len]);
else{
sum+=len;len++;
if (sum==x+1){
//printf("%I64d %I64d\n",jiecheng[len+1],2*(len));
printf("%I64d\n",((jiecheng[len+1]*niyuan[2]%mod)*niyuan[len]%mod));
}
else{
printf("%I64d\n",jiecheng[len]*niyuan[sum-x]%mod);
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: