hdu 5976 Detachment(乘法逆元)(附测试用例)

来源:互联网 发布:韩顺平java全套视频 编辑:程序博客网 时间:2024/05/18 01:23

总结来说,一个数取过模之后,他只能用逆元,不能再向以前一样.
这题的做法本身很简单,分解成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_backtypedef 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 longconst 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;}
原创粉丝点击