总结来说,一个数取过模之后,他只能用逆元,不能再向以前一样.
这题的做法本身很简单,分解成2~k,就是最大.
主要就是记录下乘法逆元这个事情.
假如(a/b)%m = c
那么如果a或b是很大的,那么他们不能被直接计算出,所以要取余,那么,对a和b取余之后,(a%mb)/b就不等于c了,因为a和b都取过余了.
那么要对a,b取余时怎么办呢,就用这个叫乘法逆元的东西,(a*k)%m = c,k是b对m的乘法逆元.`
/* xzppp */
#include <iostream>
#include <vector>
#include <cstdio>
#include <string.h>
#include <algorithm>
#include <queue>
#include <map>
#include <math.h>
#include <string>
using namespace std;
#define FFF freopen("in.txt","r",stdin);freopen("out.txt","w",stdout);
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define MP make_pair
#define PB push_back
typedef long long LL;
typedef unsigned long long ULL;
const int MAXN = 100000+17;
const int MAXM = 20;
const int INF = 0x7fffffff;
const int MOD = 1e9+7;
LL add[MAXN],mul[MAXN];
LL egcd(LL a, LL b, LL& x, LL& y)
{
LL d = a;
if(b != 0){
d = egcd(b, a % b, y, x);
y -= (a / b) * x;
}else {
x = 1;
y = 0;
}
return d;
}
LL inv(LL a, LL m)
{
LL x, y;
egcd(a, m, x, y);
return (m + x % m) % m;
}
int main()
{
#ifndef ONLINE_JUDGE
FFF
#endif
add[1] = 0; mul[1] = 1;
for (int i = 2; i < MAXN; ++i)
{
add[i] = i+add[i-1];
mul[i] = (mul[i-1]*i)%MOD;
}
int t;
cin>>t;
while(t--)
{
int n;
scanf("%d",&n);
if(n==1)
{
printf("1\n");
continue;
}
int l = -1,r = MAXN;
while(r-l>1)
{
int mid = (r+l)>>1;
if(add[mid]<=n)
l = mid;
else
r = mid;
}
int sub = n - add[l];
LL ans = -1;
if(sub>=l-1)
ans = (1LL*(mul[l]*inv(2,MOD))%MOD*(l+sub-(l-2)))%MOD;
else if(sub!=0)
ans = (1LL*mul[l+1])*inv(l-sub+1,MOD)%MOD;
else
ans = mul[l];
printf("%lld\n",ans);
}
return 0;
}
测试代码
#define FFF freopen("in.txt","r",stdin);//freopen("out.txt","w",stdout);
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define LL long long
const int maxn = 1e5;
const LL mod = 107;
LL add[maxn], mul[maxn];
void exgcd(LL a, LL b, LL& d, LL& x, LL& y){ //扩展欧几里得
if(!b){ d = a; x = 1; y = 0;}
else{
exgcd(b, a%b, d, y, x);
y -= x*(a/b);
}
}
LL inv(LL a, LL n){ //求逆元
LL d, x, y;
exgcd(a, n, d, x, y);
return (x+n)%n;
}
void init(){
memset(add, 0, sizeof(add));
memset(mul, 0, sizeof(mul));
add[0] = add[1] = 1;
add[2] = 2;
mul[0] = mul[1] = 1;
mul[2] = 2;
for(LL i = 3; i < maxn; i++){
add[i] = add[i-1]+i;
mul[i] = (mul[i-1]*i)%mod;
}
}
int main(){
#ifndef ONLINE_JUDGE
FFF
#endif
cout<<"in"<<endl;
init();
cout<<mul[20]<<" "<<mul[10]<<endl;
LL a = 1,b=1;
for (int i = 2; i <= 15; ++i)
{
a*=i;
}
for (int i = 2; i <= 10; ++i)
{
b*=i;
}
b = 2;
cout<<a<<" "<<b<<endl;
cout<<a/b<<" "<<(a/b)%mod<<endl;
cout<<(a*inv(b,mod))%mod<<endl;
cout<<(double)mul[15]/mul[10]<<endl;
cout<<mul[15]*inv(mul[10],mod)%mod<<endl;
cout<<(mul[15]%(mod*mul[10]))/mul[10]<<endl;
cout<<(a%(b*mod))/b<<endl;
return 0;
}