想要乘积大,那么挑的数肯定要越相近越好。想过分治,但是不能保证挑的数不重复。
并且要满足sum(1,m) >= n。所以基于1,2,3,..m的数列。。于是对于1-m每个数都加上(n-sum(m))/m,再从后往前把多余的数值补上去。。
其实这是打表发现的。。= =
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
#define ll long long
ll mod = 1000000007;
ll check(ll x)
{
ll a = x/2;
if(!(x%2)) return (1+x)*a;
else return ((1+x)*a%mod+a+1);
}
int main()
{
ll t,n,m;
cin>>t;
while(t--)
{
scanf("%lld%lld",&n,&m);
ll sum=1;
ll test = check(m);
if(test>n) {cout<<"-1"<<endl;continue;}
if(test==n)
{
for(ll i=1;i<=m;i++)
{
sum=(sum*i)%mod;
}
printf("%lld\n",sum);
continue;
}
ll a=(n-test)/m,b=(n-test)%m;
for(ll i=a+m,j=0;j<m;j++,i--)
{
if(b>0)
{
sum=(sum*(i+1));
b--;
}
else
{
sum=(sum*i);
}
sum%=mod;
}
printf("%lld\n",sum);
}
return 0;
}