HDU

来源:互联网 发布:时雨改二数据 编辑:程序博客网 时间:2024/06/10 14:27

题目描述:点击打开链接

题意也很简单,不解释。其实这题脑洞做法并不是我想出来的,队友想出来的做法我只负责了代码实现而已,关于做法,这题的分割方案举个例子比如7,7=2+3,后面加不了4了,并且还多出2那么我开始从3开始倒着每个数+1变成7=3+4所以答案就是3*4=12,在比如17=2+3+4+5,这是加不了6,并且还差3那么我们就把这3倒着每个数+1变成17=2+4+5+6,所以答案就是2*4*5*6=240,这样应该是解释的比较清楚了,那么讨论一下特殊情况就是我们从2开始累加完之后,还差的数字把每个数都加了1之后还差,比如13=2+3+4这里加不了5,那么把还差的4倒着每个数加1之后变成13=3+4+5这个时候还差1,那么就变成3+4+6这就是最终的答案,并且我们会发现这就是最极限的情况了,最多就是最后一个数+2,其他数都+1不会出现倒数第二个数甚至更前面的数+2的情况。那么讨论完做法之后,关于具体的实现,我们可以先把累加和打个表把阶乘也打个表,每次找到第一个大于该数x的位置然后-1就找到了前面有几个数,然后求出求出还差多少,讨论一下这个差值的情况如果不会出现最后一个数+2的情况的话那么只需要找到+1的最前面的一个位置就可以了,比如17我们找到2+3+4+5发现差2,补完之后是2+3+5+6实际上就是6!/4。而对于最后一个数+2的情况其实就是原来最后一个数+2的阶乘除2和原来最后最后一个数+1,比如13一开始我们找到2+3+4最后补完是3+4+6实际上就是6!/2*5。最后关于除法取模的问题,用费马小定理求一下逆元就好了。

AC代码:

#include<iostream>#include<sstream>#include<cstdio>#include<cstring>#include<string>#include<cmath>#include<vector>#include<stack>#include<queue>#include<algorithm>using namespace std;const long long MOD=1e9+7;const int MAXM=45000;long long x;long long sum[MAXM+10];long long mul[MAXM+10];void init(){    sum[1]=0;    for (long long i=2;i<=MAXM;i++)        sum[i]=(sum[i-1]+i);    mul[1]=1;    for (long long i=2;i<=MAXM;i++)        mul[i]=(mul[i-1]*i)%MOD;}long long qpow(long long x,long long y){    long long res=1;    while(y) {        if (y&1) res=(res*x)%MOD;        x=(x*x)%MOD;        y=y>>1;    }    return res;}int main(){    int T;    scanf("%d",&T);    init();    while(T--)    {        scanf("%lld",&x);        if (x==1) {            printf("1\n");            continue;        }        int index=upper_bound(sum+2,sum+2+MAXM+10,x)-sum;       // cout<<index<<endl;        index--;       // cout<<index<<endl;        long long sub=x-sum[index];        //cout<<sub<<endl;        long long ans;        if (sub==(long long)(index-1)) {            ans=mul[index+1]*(qpow(2,MOD-2)%MOD)%MOD;        }        else if (sub==(long long)index) {            ans=(mul[index+2])%MOD*qpow(2*(index+1)%MOD,MOD-2)%MOD;            //cout<<ans<<endl;        }        else {            ans=(mul[index+1])%MOD*qpow(index-sub+1,MOD-2)%MOD;        }        printf("%lld\n",ans);    }    return 0;}


原创粉丝点击