HDU 5976 && 2016ICPC大连 F: Detachment(找规律)

来源:互联网 发布:网页下载app源码 编辑:程序博客网 时间:2024/05/29 16:20



题意:

将n拆成a1+a2+a3+…+ax的形式(ai≠aj),让a1*a2*a3*…*ax的值最大,求这个最大值


找规律

n=35:2+3+4+5+6+7+8;      max:2*3*4*5*6*7*8

n=36:2+3+4+5+6+7+8+1;  max:2*3*4*5*6*7*9

n=37:2+3+4+5+6+7+8+2;  max:2*3*4*5*6*8*9

n=38:2+3+4+5+6+7+8+3;  max:2*3*4*5*7*8*9

n=39:2+3+4+5+6+7+8+4;  max:2*3*4*6*7*8*9

n=40:2+3+4+5+6+7+8+5;  max:2*3*5*6*7*8*9

n=41:2+3+4+5+6+7+8+6;  max:2*4*5*6*7*8*9

n=42:2+3+4+5+6+7+8+7;  max:3*4*5*6*7*8*9

n=43:2+3+4+5+6+7+8+8;  max:3*4*5*6*7*8*10

n=41:2+3+4+5+6+7+8+9;  max:3*4*5*6*7*8*9*10(一波循环)

……

阶乘和乘法逆元都打表(打到100000就够了),每次计算把中间缺的那个除掉

寻找临界点用二分


#include<stdio.h>#include<string.h>#include<algorithm>using namespace std;#define mod 1000000007#define LL long longLL jc[100005] = {1,1}, er[100005] = {0,0,2}, nv[100005];LL Pow(LL x, LL y){LL sum = 1;while(y){if(y%2)sum = sum*x%mod;x = x*x%mod;y /= 2;}return sum;}int main(void){LL T, i, n, x, r;for(i=2;i<=100000;i++)jc[i] = (jc[i-1]*i)%mod;for(i=3;i<=100000;i++)er[i] = er[i-1]+i;for(i=2;i<=100000;i++)nv[i] = Pow(i, mod-2);scanf("%lld", &T);while(T--){scanf("%lld", &n);if(n<=4){printf("%lld\n", n);continue;}x = lower_bound(er+1, er+100001, n)-er;if(er[x]==n)printf("%lld\n", jc[x]);else{r = n-er[x-1];if(r==x-1)printf("%lld\n", jc[x-1]*(x+1)%mod*nv[2]%mod);elseprintf("%lld\n", jc[x]*nv[x-r]%mod);}}return 0;}

原创粉丝点击