题目链接
题意:给一个x数,可以将他拆成多个整数,并且这些整数互不相同,使得累积和最大,求累积和最大,最后取模1e9+7
题解:思考:如果将x拆成多个2的话会让答案值最大,然后再拆成三,再拆成4.....以此类推
要使答案最大可以从2 3 4 5 ....一直枚举下去,然后将剩余的k值对前面的进行遍历累加,当出现某个数a+k没有与之前重复时,这样会保证答案最大
先预处理出前缀积,然后将符合条件前缀积除去a,乘上a+k
除法因为出现取模情况,转为乘法逆元
乘法逆元:
ll ext_gcd(ll a,ll b,ll &x,ll &y)
{
ll t,d;
if(b==0) {x=1;y=0;return a;
}
d=ext_gcd(b,a%b,x,y);
t=x;
x=y;
y=t-a/b*y;
return d;
}
ll Invmod(ll a)
{
ll x,y;
if(ext_gcd(a,mod,x,y)!=1) return -1;
return (x%mod+mod)%mod;
}
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define pb push_back
ll sum[100005];
ll mult[100005];
const ll mod = 1e9+7;
ll ext_gcd(ll a,ll b,ll &x,ll &y)
{
ll t,d;
if(b==0) {x=1;y=0;return a;
}
d=ext_gcd(b,a%b,x,y);
t=x;
x=y;
y=t-a/b*y;
return d;
}
ll Invmod(ll a)
{
ll x,y;
if(ext_gcd(a,mod,x,y)!=1) return -1;
return (x%mod+mod)%mod;
}
int main()
{
ll x,i;
int t;
sum[1]=0,mult[1]=1;
for(i=2;i<100005;i++)
{
sum[i]=sum[i-1]+i;
}
for(i=2;i<100005;i++)
{
mult[i]=mult[i-1]*i%mod;
}
scanf("%d",&t);
while(t--)
{
ll k=0,st=0,i=0;
scanf("%d",&x);
if(x==1){printf("%d
",x);continue;
}
i=upper_bound(sum+1,sum+100005,x)-sum;
k=x-sum[i-1];
st=i-1;
i=2;
while(1)
{
if(k+i>st)
{
break;
}
i++;
}
ll ans=(mult[st]*Invmod(i)%mod)*(k+i)%mod;
printf("%lld
",ans);
}
return 0;
}