zoukankan      html  css  js  c++  java
  • luogu3704 [SDOI2017]数字表格(莫比乌斯反演)

    link

    (f_0=0,f_1=1,f_n=f_{n-1}+f_{n-2}(nge 2))

    (prod_{i=1}^nprod_{j=1}^mf_{gcd(i,j)}),多组询问,(Tle1000,n,mle10^6)

    推导过程稍微有点难,因为有prod而不是清一色的sum了 不过总体还是不难的

    (prod_{i=1}^nprod_{j=1}^mf_{gcd(i,j)})

    (=prod_{p=1}^nf_p^{sum_{i=1}^nsum_{j=1}^m[gcd(i,j)=p]})

    (=prod_{p=1}^nf_p^{sum_{i=1}^{n/p}sum_{j=1}^{m/p}[gcd(i,j)=1]})

    (=prod_{p=1}^nf_p^{sum_{i=1}^{n/p}sum_{j=1}^{m/p}sum_{d|i,d|j}mu(d)})

    (=prod_{p=1}^nf_p^{sum_{d=1}^nmu(d)lfloorfrac n{pd} floorlfloorfrac m{pd} floor})

    (=prod_{p=1}^nf_p^{sum_{d=1}^nmu(d)lfloorfrac n{pd} floorlfloorfrac m{pd} floor})

    (=prod_{q=1}^nleft(prod_{d|q}f_{q/d}^{mu(d)} ight)^{lfloorfrac n{q} floorlfloorfrac m{q} floor})

    (就最后一步好像难一点

    线性筛(mu)

    (prod_{d|q}f_{q/d}^{mu(d)})部分可以nlogn枚举倍数预处理

    然后做个前缀乘积,后面直接打个逆元就行了

    (O(tsqrt nlog n))

    #include <cstdio>
    #include <iostream>
    using namespace std;
    
    const int p = 1000000007;
    int f[1000010], invf[1000010], fuck = 1000000, mu[1000010], prime[1000000], tot;
    int s[1000010];
    bool vis[1000010];
    
    int qpow(int x, long long y)
    {
    	int res = 1;
    	while (y > 0)
    	{
    		if (y & 1) res = res * (long long)x % p;
    		x = x * (long long)x % p;
    		y >>= 1;
    	}
    	return res;
    }
    
    int main()
    {
    	mu[1] = 1;
    	for (int i = 2; i <= fuck; i++)
    	{
    		if (vis[i] == false) prime[++tot] = i, mu[i] = -1;
    		for (int j = 1; j <= tot && i * prime[j] <= fuck; j++)
    		{
    			vis[i * prime[j]] = true;
    			if (i % prime[j] == 0) break;
    			mu[i * prime[j]] = -mu[i];
    		}
    	}
    	f[1] = invf[1] = s[1] = 1;
    	for (int i = 2; i <= fuck; i++) f[i] = (f[i - 1] + f[i - 2]) % p, invf[i] = qpow(f[i], p - 2), s[i] = 1;
    	for (int d = 1; d <= fuck; d++)
    	{
    		if (mu[d] == -1)
    			for (int q = d, cnt = 1; q <= fuck; q += d, cnt++)
    				s[q] = s[q] * (long long)invf[cnt] % p;
    		if (mu[d] == 1)
    			for (int q = d, cnt = 1; q <= fuck; q += d, cnt++)
    				s[q] = s[q] * (long long)f[cnt] % p;
    	}
    	s[0] = 1;
    	for (int i = 2; i <= fuck; i++) s[i] = s[i] * (long long)s[i - 1] % p;
    	int t;
    	scanf("%d", &t);
    	while (t --> 0)
    	{
    		int ans = 1;
    		int n, m; scanf("%d%d", &n, &m); if (n > m) { int t = n; n = m; m = t; }
    		for (int i = 1, j; i <= n; i = j + 1)
    		{
    			j = min(n / (n / i), m / (m / i));
    			ans = ans * (long long)qpow(s[j] * (long long)qpow(s[i - 1], p - 2) % p, (n / i) * (long long)(m / i)) % p;
    		}
    		printf("%d
    ", ans);
    	}
    	return 0;
    }
    

    这次终于不用define int long long可

  • 相关阅读:
    Demo:刮刮卡橡皮擦效果
    养成良好的代码编写习惯
    我的百科
    专业英语词汇
    加载资源的类
    循环滚动翻页+居中项缩放
    学习笔记—Node中模块化规范
    学习笔记—Node中的EventLoop
    学习笔记—Node的全局对象
    学习笔记—Node的基本概念
  • 原文地址:https://www.cnblogs.com/oier/p/10297361.html
Copyright © 2011-2022 走看看