bzoj 4816: [Sdoi2017]数字表格

本文介绍了一种解决特定数学问题的方法,利用数论中的性质与线性筛算法相结合来高效求解。通过对题目进行转换和优化,实现了在大数据集下快速计算的目标。

题目大意:

\(\prod_{i=1}^n\prod_{j=1}^mf(gcd(i,j))\)
\(f(0) = 0\),\(f(1) = 1\),\(f(i) = f(i-1) + f(i-2)\)
数据组数T <= 1000; n,m <= 10^6

题解.

\[\prod_{i=1}^n\prod_{j=1}^mf(gcd(i,j))\]
\[\prod_{x=1}^nf(x)^{\sum_{i=1}^n\sum_{j=1}^n[gcd(i,j) = x]}\]
\[\prod_{x=1}^nf(x)^{\sum_{i=1}^{\frac{n}{x}}\sum_{j=1}^{\frac{m}{x}}[gcd(i,j) = 1]}\]
\[\prod_{x=1}^nf(x)^{\sum_{d=1}^{\frac{n}{x}}\mu(d)*[\frac{n}{dx}]*[\frac{m}{dx}]}\]
\[\prod_{T=1}^n(\prod_{d|T}f(d)^{\mu(\frac{T}{d})})^{[\frac{n}{T}]*[\frac{m}{T}]}\]

设 : \(g(T) = \prod_{d|T}f(d)^{\mu(\frac{T}{d})}\)

如果可以快速预处理\(g(x)\)就可以做到单次\(O(\sqrt{n}\log n)\)
那么考虑如何快速预处理\(g(T)\)
考虑到\(\mu(x)\)有不少是0,剩下的只有1/-1两种取值.
那么对于单个的\(g(T)\)的计算可以只枚举所有有用的取值.
在T的约数中只选取mu值不为0的值进行统计.
相同的质因子最多包含一个.所以发现可以找出所有不相同的质因子.
显然个数少到可以状压起来 (35711131719 = 4849845 > 1000000)
所以状压一下每个质因子是否选取.相应的进行函数值的计算.

为了辅助快速找出所有不同的质因子
可以提前线性筛出所有数的最小质因子及除去这个最小因子后成为的数。
单点求出所有的\(g(x)\)后就可以直接分块处理每个询问了.

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
inline void read(int &x){
    x=0;static char ch;static bool flag;flag = false;
    while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
    while(x=(x<<1)+(x<<3)+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
}
#define rg register int
#define rep(i,a,b) for(rg i=(a);i<=(b);++i)
#define per(i,a,b) for(rg i=(a);i>=(b);--i)
const int maxn = 1000010;
const int mod = (1e9 + 7);
int pri[maxn],cnt,mu[maxn],minp[maxn],oth[maxn];
bool vis[maxn];
inline ll qpow(ll x,ll p){
    ll ret = 1;
    for(;p;p>>=1,x=1LL*x*x%mod) if(p&1) ret = 1LL*ret*x % mod;
    return ret;
}
inline void liner(int n){
    mu[1] = minp[1] = oth[1] = 1;
    rep(i,2,n){
        if(!vis[i]){
            pri[++cnt] = i;
            mu[i] = -1;
            minp[i] = i;
            oth[i] = 1;
        }
        rep(j,1,cnt){
            ll x = 1LL*i*pri[j];
            if(x > n) break;
            vis[x] = true;
            if(i % pri[j] == 0){
                minp[x] = minp[i];
                oth[x] = oth[i];
                mu[x] = 0;
                break;
            }
            mu[x] = -mu[i];
            minp[x] = pri[j];
            oth[x] = i;
        }
    }
}
int g[maxn],f[maxn],d[maxn];
#define lowbit(x) (x&-x)
inline int calc(int T){
    ll ups = f[T],dns = 1;
    static int a[22],cnt;
    cnt = 0;
    for(int x=T;x!=1;x=oth[x])a[++cnt]=minp[x];
    d[0] = 1;
    for(int i=1;i<=cnt;++i) d[1<<i-1] = a[i];
    for(int s=1,x;s<(1<<cnt);++s){
        x = lowbit(s);
        d[s] = d[s^x]*d[x];
        if(mu[d[s]] == 1) ups = 1LL*ups*f[T/d[s]] % mod;
        else dns = 1LL*dns*f[T/d[s]] % mod;
    }
    return 1LL*ups*qpow(dns,mod-2) % mod;
}
int main(){
    liner(1000000);
    int n,m;
    n = 1000000;
    f[0] = 0;f[1] = 1;
    rep(i,2,n){
        f[i] = f[i-1] + f[i-2];
        if(f[i] >= mod) f[i] -= mod;
    }
    rep(i,1,n) g[i] = calc(i);
    rep(i,2,n) g[i] = 1LL*g[i-1]*g[i] % mod;
    g[0] = 1;
    int T;read(T);
    while(T--){
        read(n);read(m);
        if(n > m) swap(n,m);
        int ans = 1;
        for(int i=1,j;i <= n;i = j+1){
            j = min(n / (n/i),m / (m/i));
            ans =1LL*ans*qpow(1LL*g[j]*qpow(g[i-1],mod-2)%mod,1LL*(n/i)*(m/i)%(mod-1)) % mod;
        }
        printf("%d\n",ans);
    }
    return 0;
}

转载于:https://www.cnblogs.com/Skyminer/p/6710769.html

标题基于Python的自主学习系统后端设计与实现AI更换标题第1章引言介绍自主学习系统的研究背景、意义、现状以及本文的研究方法和创新点。1.1研究背景与意义阐述自主学习系统在教育技术领域的重要性和应用价值。1.2国内外研究现状分析国内外在自主学习系统后端技术方面的研究进展。1.3研究方法与创新点概述本文采用Python技术栈的设计方法和系统创新点。第2章相关理论与技术总结自主学习系统后端开发的相关理论和技术基础。2.1自主学习系统理论阐述自主学习系统的定义、特征和理论基础。2.2Python后端技术栈介绍DjangoFlask等Python后端框架及其适用场景。2.3数据库技术讨论关系型和非关系型数据库在系统中的应用方案。第3章系统设计与实现详细介绍自主学习系统后端的设计方案和实现过程。3.1系统架构设计提出基于微服务的系统架构设计方案。3.2核心模块设计详细说明用户管理、学习资源管理、进度跟踪等核心模块设计。3.3关键技术实现阐述个性化推荐算法、学习行为分析等关键技术的实现。第4章系统测试与评估对系统进行功能测试和性能评估。4.1测试环境与方法介绍测试环境配置和采用的测试方法。4.2功能测试结果展示各功能模块的测试结果和问题修复情况。4.3性能评估分析分析系统在高并发等场景下的性能表现。第5章结论与展望总结研究成果并提出未来改进方向。5.1研究结论概括系统设计的主要成果和技术创新。5.2未来展望指出系统局限性并提出后续优化方向。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值