LOJ6102「2017 山东二轮集训 Day1」第三题 【min-max容斥,反演】

题目描述:输入一个大小为\(n\)的集合\(S\),求\(\text{lcm}_{k\in S}f_k\),其中\(f_k\)是第$$个Fibonacci数。

数据范围:\(n\le 5\times 10^4,u\le 10^6\)

数论经典题?

首先你要想到min-max容斥。

\[\text{lcm}(f_S)=\prod_{\varnothing\ne T\subseteq S}\gcd(f_T)^{(-1)^{|T|-1}} \]

然后你知道\(\gcd(f_a,f_b)=f_\gcd(a,b)\),所以。

\[\text{lcm}(f_S)=\prod_{\varnothing\ne T\subseteq S}f_{\gcd(T)}^{(-1)^{|T|-1}} \]

不知道为什么你开始反演,设\(f_n=\prod\limits_{d|n}g_d\),则\(g_n=\prod\limits_{d|n}f_{d}^{\mu(\frac{n}{d})}\)

\[\begin{aligned} \text{lcm}(f_S)&=\prod_{\varnothing\ne T\subseteq S}(\prod_{d|\gcd(T)}g_d)^{(-1)^{|T|-1}} \\ &=\prod_{d}g_d^{\sum\limits_{\varnothing\ne T\subseteq S,d|T}(-1)^{|T|-1}} \end{aligned} \]

我们看看指数是啥。设\(S_d=\{n|n\in S\and d|n\}\)

\[\sum_{\varnothing\ne T\subseteq S_d}(-1)^{|T|-1}=[|S_d|>0] \]

所以

\[\text{lcm}(f_S)=\prod_{\exist a\in S,d|a}g_d \]

直接做,时间复杂度\(O(k\log k)\)

code ```cpp #include #define Rint register int using namespace std; typedef long long LL; const int mod = 1e9 + 7, N = 1000003; int n, a[N], mx, f[N], g[N], ans = 1; bool vis[N]; inline int add(int a, int b){return (a + b >= mod) ? (a + b - mod) : (a + b);} inline int kasumi(int a, int b){ int res = 1; while(b){ if(b & 1) res = (LL) res * a % mod; a = (LL) a * a % mod; b >>= 1; } return res; } int main(){ scanf("%d", &n); for(Rint i = 1;i <= n;i ++) scanf("%d", a + i), vis[a[i]] = true, mx = max(mx, a[i]); for(Rint i = 1;i <= mx;i ++) for(Rint j = (i << 1);j <= mx;j += i) vis[i] |= vis[j]; f[0] = 0; f[1] = g[1] = 1; for(Rint i = 2;i <= mx;i ++) f[i] = add(f[i - 1], f[i - 2]), g[i] = 1; for(Rint i = 1;i <= mx;i ++){ int tmp = kasumi(g[i] = (LL) g[i] * f[i] % mod, mod - 2); for(Rint j = (i << 1);j <= mx;j += i) g[j] = (LL) g[j] * tmp % mod; } for(Rint i = 1;i <= mx;i ++) if(vis[i]) ans = (LL) ans * g[i] % mod; printf("%d", ans); } ```
posted @ 2019-11-07 16:56  mizu164  阅读(197)  评论(0编辑  收藏  举报