CodeChef:Fombinatorial(数论 & 逆元)

来源:互联网 发布:c语言开发工具 win10 编辑:程序博客网 时间:2024/06/04 19:11

You are given a function f which is defined as :




Your task is to find the value of f(N) / ( f(r)*f(N-r) )

. As it will be a large number output it modulo M.

Input

First line contains T , number of test cases to follow.

Next follows T test case.

First line of ever test case contain 3 space separated integers N , M and Q.

Next Q line follows , each line contain r.

Output

For every test case , output Q lines , each line containing the answer.

Constraints

  • 2 ≤ N ≤ 105
  • 1 ≤ M ≤ 109
  • 2 ≤ Sum of N over all test cases ≤ 5*105
  • 2 ≤ Sum of Q over all test cases ≤ 105
  • 1 < r < N

Subtasks

  • Subtask 1: N ≤ 5 , rest of the constraints are same. Points - 9
  • Subtask 2: N ≤ 500 , M is a prime number , rest of the constraints are same. Points - 31
  • Subtask 3: Refer to constraints above : Points-60

Sample Input

15 24 223

Sample Output

88

Explanation

f[1] = 1

f[2] = 4

f[3] = 1*22*33 = 108

f[4] =1*22*33*44 = 27648

f[5] = 1*22*33*44*55 =86400000

value of f[5] / (f[2]*f[3]) = 200000 and 200000%24 is 8

题意:给N,M,Q,Q个询问,每个询问给个r,输出f(N) / ( f(r)*f(N-r) )对m取模。  

思路:假如f(x)均与m互素,那么可以预处理f(N)然后求出分子的逆元即可,由于m不一定为素数求逆元用扩展欧几里方便一点,那么目标就是将f(x)变成与m互素,即将f(1~N)分解质因子,出现f(N)的质因子均提出来另外存起来,最后分成两部分计算即可。

# include <bits/stdc++.h># define LL long long# define M map<LL, LL># define A first# define B secondusing namespace std;const int maxn = 1e5+30;int t, n, q, cnt=2, p[maxn]={2,3};LL gd, m, x, y, co[maxn];M nco[maxn];void init(){    for(int i=5, j=0; i<maxn-1; ++i,j=0)    {        for(;p[j]<=sqrt(i); ++j)            if(i%p[j] == 0)                break;        if(i%p[j] !=0 ) p[cnt++] = i;    }}LL qmod(LL a, LL b){    LL ans = 1;    for(;b;b>>=1)    {        if(b&1) ans = ans*a%m;        a =a*a%m;    }    return ans;}LL ex_gcd(LL a, LL b){    if(b == 0)    {        x = 1;        y = 0;        return a;    }    gd = ex_gcd(b, a%b);    LL t = x;    x = y;    y = t-(a/b)*y;    return gd;}int main(){    init();    scanf("%d",&t);    while(t--)    {        scanf("%d%lld%d",&n,&m,&q);        for(int i=1; i<=n; ++i) co[i] = 1LL, nco[i].clear();        for(int i=0; p[i]<=n; ++i)        {            for(int j=1; j*p[i]<=n; ++j)            {                LL tmp = j*p[i], tot=0, num = tmp;                while(tmp%p[i] == 0)                    ++tot, tmp /= p[i];                tot = num*tot;                if(__gcd(m, (LL)p[i]) != 1)                    nco[num][p[i]] += tot;                else                    co[num] = co[num]*qmod(p[i], tot)%m;            }        }        for(int i=2; i<=n; ++i)        {            co[i] = co[i] * co[i-1]%m;            for(auto it = nco[i-1].begin(); it != nco[i-1].end(); ++it)                nco[i][it->A] += it->B;        }        while(q--)        {            LL r;            scanf("%lld",&r);            LL ans = co[r]*co[n-r]%m;            ex_gcd(ans, m);            ans = (x%m+m)%m;            for(auto it = nco[n].begin(); it != nco[n].end(); ++it)            {                LL tmp = qmod(it->A, it->B - nco[r][it->A] - nco[n-r][it->A]);                ans = ans*tmp%m;            }            ans = ans*co[n]%m;            printf("%lld\n",ans);        }    }    return 0;}


原创粉丝点击