• P3704 [SDOI2017]数字表格


    (color{#0066ff}{ 题目描述 })

    Doris刚刚学习了fibonacci数列。用(f[i])表示数列的第(i)项,那么

    (f[0]=0),(f[1]=1),

    (f[n]=f[n-1]+f[n-2]),(ngeq 2)

    Doris用老师的超级计算机生成了一个(n×m)的表格,

    (i)行第(j)列的格子中的数是(f[gcd(i,j)]),其中(gcd(i,j))表示(i,j)的最大公约数。

    Doris的表格中共有(n×m)个数,她想知道这些数的乘积是多少。

    答案对(10^9+7)取模。

    (color{#0066ff}{输入格式})

    有多组测试数据。

    第一个一个数(T),表示数据组数。

    接下来(T)行,每行两个数(n,m)

    (color{#0066ff}{输出格式})

    输出(T)行,第(i)行的数是第(i)组数据的结果

    (color{#0066ff}{输入样例})

    3
    2 3
    4 5
    6 7
    

    (color{#0066ff}{输出样例})

    1
    6
    960
    

    (color{#0066ff}{数据范围与提示})

    (10\%)的数据,(1leq n,mleq 100)

    (30\%)的数据,(1leq n,mleq 1000)

    另外存在(30\%)的数据,(Tleq 3)

    (100\%)的数据,(Tleq1000,1leq n,mleq 10^6)

    时间限制:5s

    内存限制:128MB

    (color{#0066ff}{ 题解 })

    题目要求这东西

    [prod_{i=1}^n prod_{j=1}^m f[gcd(i,j)] ]

    枚举gcd

    [prod_{d=1}^{min(n,m)}prod_{i=1}^n prod_{j=1}^m [gcd(i,j)==d]f(d) ]

    改成枚举gcd然后变成(sum),并放到指数位置

    [prod_{d=1}^{min(n,m)}f(d)^{sum_{i=1}^{lfloorfrac{n}{d} floor} sum_{j=1}^{lfloorfrac{m}{d} floor} [gcd(i,j)==1]} ]

    (mu)换一下

    [prod_{d=1}^{min(n,m)}f(d)^{sum_{i=1}^{lfloorfrac{n}{d} floor} sum_{j=1}^{lfloorfrac{m}{d} floor}sum_{k|gcd(i,j)} mu(k)} ]

    [prod_{d=1}^{min(n,m)}f(d)^{sum_{k=1}^{min(lfloorfrac{n}{d} floor,lfloorfrac{m}{d} floor} mu(k) * lfloorfrac{n}{kd} floor*lfloorfrac{m}{kd} floor} ]

    kd换q

    [prod_{q=1}^{min(n,m)}prod_{d|q}f(d)^{ mu(frac q d) * lfloorfrac{n}{q} floor*lfloorfrac{m}{q} floor} ]

    [prod_{q=1}^{min(n,m)}prod_{d|q}(f(d)^{ mu(frac q d) }) ^ { lfloorfrac{n}{q} floor*lfloorfrac{m}{q} floor} ]

    发现括号的部分可以(O(nlogn))处理出来,然后数列分块就行了

    #include<bits/stdc++.h>
    #define LL long long
    LL in() {
    	char ch; LL x = 0, f = 1;
    	while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
    	for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
    	return x * f;
    }
    const int maxn = 1e6 + 10;
    const int mod = 1e9 + 7;
    LL f[maxn], mu[maxn], pri[maxn], tot, h[maxn];
    bool vis[maxn];
    LL ksm(LL x, LL y) {
    	LL re = 1LL;
    	while(y) {
    		if(y & 1) re = re * x % mod;
    		x = x * x % mod;
    		y >>= 1;
    	}
    	return re;
    }
    int mi(LL a, LL b) {
    	if(b == 1) return a;
    	if(b == 0) return 1;
    	if(b == -1) return ksm(a, mod - 2);
    	assert(0);
    	return 2333333;
    }
    void predoit() {
    	mu[1] = 1;
    	for(int i = 2; i < maxn; i++) {
    		if(!vis[i]) pri[++tot] = i, mu[i] = -1;
    		for(int j = 1; j <= tot && (LL)i * pri[j] < maxn; j++) {
    			vis[i * pri[j]] = true;
    			if(i % pri[j] == 0) break;
    			else mu[i * pri[j]] = -mu[i];
    		}
    	}
    	f[0] = 0, f[1] = 1;
    	for(int i = 2; i < maxn; i++) f[i] = (f[i - 1] + f[i - 2]) % mod;
    	for(int i = 0; i < maxn; i++) h[i] = 1;
    	for(int i = 1; i < maxn; i++)
    		for(int j = i; j < maxn; j += i) 
    			h[j] = h[j] * mi(f[i], mu[j / i]) % mod;
    	for(int i = 2; i < maxn; i++) h[i] = (h[i] * h[i - 1]) % mod;
    }
    LL work(LL n, LL m) {
    	LL ans = 1;
    	for(LL l = 1, r; l <= std::min(n, m); l = r + 1) {
    		r = std::min(n / (n / l), m / (m / l));
    		ans = ans * ksm(h[r] * ksm(h[l - 1], mod - 2) % mod, (n / l) * (m / l)) % mod;
    	}
    	return ans;
    }
    int main() {
    	predoit();
    	for(int T = in(); T --> 0;) printf("%lld
    ", work(in(), in()));
    	return 0;
    }
    
  • 相关阅读:
    041 Spring Boot中排除功能的处理
    015 图像验证码
    040 Http与RPC
    039 在weblogic下部署jndi的多数据源
    038 lock wait timeout exceeded;try restarting transaction
    037 关于微服务的认识
    036 互联网的框架演变
    035 控制并发 select * from test1 where id =1 for update 就会对这行加锁了?
    034 Maven中的dependencyManagement和dependencies区别
    014 Security的认证流程源码级详解
  • 原文地址:https://www.cnblogs.com/olinr/p/10301841.html
Copyright © 2020-2023  润新知