HDU5407——最小公倍数+逆元求法——CRB and Candies
逆元 inv
应用于取模运算中
加法 (a + b) % p = a % p + b % p;
减法 (a - b) % p = a % p - b % p;
乘法 (a * b) % p = a % p * b % p;
但是除法
(a / b) % p :
a * b % p = c;
已知 b, c, p 求 a
a = c * d % p
c就是b的逆元
一个数逆元求法
推导过程
第二种求法(推荐)
用快速幂o(log(b)
代码实现
ll pow_mod(ll a, ll b, ll p){ ll ret = 1%p; while(b){ if(b&1) ret = ret * 1ll * a % p; a = a * 1ll * a % p; b >>= 1; } return ret; }
好了现在知道了逆元求法,说题目
打表发现有一个规律,n的排列组合的lcm就是(1到n+1)的lcm/(n+1) % mod
知道了逆元求法,n+1解决了,那么1-n+1的lcm怎么求?
官方题解
因为p的1次2次3次这些数都是只有一个的2,4,8,16这种,一旦出现n =pow(p,k)那么说明要乘上一个最小质因子
/************************************************ * Author :Powatr * Created Time :2015-8-21 14:10:33 * File Name :1002.cpp ************************************************/ #include <cstdio> #include <algorithm> #include <iostream> #include <sstream> #include <cstring> #include <cmath> #include <string> #include <vector> #include <queue> #include <deque> #include <stack> #include <list> #include <map> #include <set> #include <bitset> #include <cstdlib> #include <ctime> using namespace std; #define lson l, mid, rt << 1 #define rson mid + 1, r, rt << 1 | 1 typedef long long ll; const int MAXN = 1e6 + 10; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; ll prim[MAXN]; ll f[MAXN]; bool ok(ll x) { ll y = prim[x]; while(x%y == 0 && x > 1) x/=y; if(x == 1) return true; return false; } void inti() { for(int i = 1; i <= MAXN; i++) prim[i] = i; for(int i = 2; i <= MAXN; i++){ if(prim[i] == i){ for(int j = i + i; j <= MAXN; j += i){ prim[j] = i; } } } f[0] = 1; for(int i = 1; i <= MAXN; i++){ if(ok(i)) f[i] = f[i-1] * prim[i] % mod; else f[i] = f[i-1]; } } ll pow_mod(ll a, ll b, ll p){ ll ret = 1%p; while(b){ if(b&1) ret = ret * 1ll * a % p; a = a * 1ll * a % p; b >>= 1; } return ret; } ll inv(ll a, ll b){ return pow_mod(a, b-2, b); } int main(){ //Eular(); inti(); int T, n; for(scanf("%d", &T); T--; ){ scanf("%d", &n); n++; ll ans = f[n] * inv(n, mod) % mod; printf("%I64d\n", ans); } return 0; }