LibreOJ2085 - 「NOI2016」循环之美

本文探讨了在特定进制下,如何计算不同纯循环小数的数量,通过数学推导和算法实现,解决了求解形式为x/y的纯循环小数问题。

Portal

Description

给出\(n,m(n,m\leq10^9)\)\(k(k\leq2000)\),求在\(k\)进制下,有多少个数值不同的纯循环小数可以表示成\(\dfrac{x}{y}\)的形式,其中\(x\in[1,n],y\in[1,m]\)。一个数是纯循环小数当且仅当它能写成\(a.\dot{c_1} c_2 c_3 \ldots c_{p-1}\dot{c_p}\)的形式。

Solution

原题相当于求有多少个数对\((x,y)\)满足\(gcd(x,y)=1\)\(\dfrac{x}{y}\)是纯循环小数。因为若\(x,y\)不互质且在范围内,将\(\dfrac{x}{y}\)化为最简分数依然在范围内。

首先考虑一个数是纯循环小数意味着什么。
\[\begin{align*} a.\dot{c_1} c_2 c_3 \ldots c_{p-1}\dot{c_p} &= a+\sum_{i=0}^{+∞}(0.c_1c_2c_3\ldots c_{p-1}c_p)_{k}\cdot k^{-ip} \\ &= a+(0.c_1c_2c_3\ldots c_{p-1}c_p)_{k}\sum_{i=0}^{+\infty}(k^{-p})^i \\ &= a+\frac{1}{1-k^{-p}}(0.c_1c_2c_3\ldots c_{p-1}c_p)_{k} \\ &= a+\frac{(c_1c_2c_3\ldots c_{p-1}c_p)_k}{k^p-1} \\ \frac{x}{y} &= a+\frac{(c_1c_2c_3\ldots c_{p-1}c_p)_k}{k^p-1} \\ \lfloor \frac{x}{y} \rfloor + \frac{x \bmod y}{y} &= a+\frac{(c_1c_2c_3\ldots c_{p-1}c_p)_k}{k^p-1} \end{align*}\]\(a=\lfloor \dfrac{x}{y} \rfloor\),那么若\(\dfrac{x \bmod y}{y}\)能表示成\(\dfrac{(c_1c_2c_3\ldots c_{p-1}c_p)_k}{k^p-1}\)的形式则说明\(\dfrac{x}{y}\)是纯循环小数。由于\(\dfrac{x \bmod y}{y}\)是最简分数,所以\(\dfrac{x}{y}\)是纯循环小数 ⇔ \(\exists p\)使得\(y|k^p-1\)\(\exists p\)使得\(k^p \bmod y = 1\)\(gcd(y,k)=1\)
于是原题相当于求
\[\begin{align*} ans &= \sum_{x=1}^n \sum_{y=1}^n [gcd(x,y)=1][gcd(y,k)=1] \\ &= \sum_{d=1}^{+∞} \mu(d) \sum_{d|x}^n \sum_{d|y}^m [gcd(y,k)=1] \\ &= \sum_{d=1}^{+∞} \mu(d) \lfloor\frac{n}{d}\rfloor \sum_{i=1}^{\lfloor\frac{m}{d}\rfloor} [gcd(id,k)=1] \\ &= \sum_{d=1}^{min(n,m)} [gcd(d,k)=1]\mu(d) \lfloor\frac{n}{d}\rfloor \sum_{i=1}^{\lfloor\frac{m}{d}\rfloor} [gcd(i,k)=1] \\ \end{align*}\]于是我们发现我们主要要求两个东西:\(f(x,k)=\sum_{i=1}^x [gcd(i,k)=1]\)\(g(x,k)=\sum_{i=1}^x [gcd(i,k)=1]\mu(i)\)。算出他们就可以利用整除分块来快速计算。
易知\(f(x,k)=\lfloor\dfrac{x}{k}\rfloor f(k,k)+f(x\bmod k,k)\),而对于\(x\in[0,k]\)我们都可以预处理出来,所以\(f\)很好求。
考虑\(g\)怎么求。将\(k\)表示成\(p^tq\)的形式,其中\(p\)是质数,\(gcd(p,q)=1\)。那么\(gcd(i,k)=1 ⇔ gcd(i,p)=1,gcd(i,q)=1\)。那么我们从满足\(gcd(i,q)=1\)\(i\)中减去\(gcd(i,p)\neq1\)\(p|i\)的部分,即:
\[\begin{align*} g(x,k) &= \sum_{i=1}^x[gcd(i,q)=1]\mu(i)-\sum_{p|i}^x[gcd(i,q)=1]\mu(i) \\ &= g(x,q)-\sum_{i=1}^{\lfloor\frac{x}{p}\rfloor}[gcd(ip,q)=1][gcd(i,p)=1]\mu(ip) \\ &= g(x,q)-\sum_{i=1}^{\lfloor\frac{x}{p}\rfloor}[gcd(i,k)=1]\mu(i)\mu(p) \\ &= g(x,q)-g(\lfloor\frac{x}{p}\rfloor,k) \end{align*}\] 易知\(g(x,1)=\sum_{i=1}^x \mu(i)\),可以用杜教筛来求。用map或哈希表来对\(g\)进行存储以进行记忆化搜索,就可以通过本题啦。

Code

//「NOI2016」循环之美
#include <cstdio>
#include <map>
using namespace std;
const int N=3e6+10;
int n,m,k;
int gcd(int x,int y) {return x%y?gcd(y,x%y):y;}
int f0[2001];
void initF() {for(int i=1;i<=k;i++) f0[i]=f0[i-1]+(gcd(i,k)==1);}
int f(int x) {return x/k*f0[k]+f0[x%k];}
int prCnt,pr[N]; bool prNot[N];
int muS[N];
void initG(int n)
{
    muS[1]=1;
    for(int i=2;i<=n;i++)
    {
        if(!prNot[i]) pr[++prCnt]=i,muS[i]=-1;
        for(int j=1;j<=prCnt;j++)
        {
            int x=i*pr[j]; if(x>n) break;
            prNot[x]=true;
            if(i%pr[j]) muS[x]=-muS[i]; else break;
        }
    }
    for(int i=1;i<=n;i++) muS[i]+=muS[i-1];
}
map<pair<int,int>,int> g1;
map<pair<int,int>,bool> getG;
int sum(int x)
{
    pair<int,int> x_1=make_pair(x,1);
    if(x<=2e6) return g1[x_1]=muS[x];
    if(getG[x_1]) return g1[x_1];
    lint res=1;
    for(int L=2,R;L<=x;L=R+1)
    {
        int v=x/L; R=x/v;
        res-=1LL*(R-L+1)*sum(v);
    }
    getG[x_1]=true;
    return g1[x_1]=res;
}
int g(int x,int k)
{
    pair<int,int> x_k=make_pair(x,k);
    if(getG[x_k]) return g1[x_k];
    if(x==0||k==1) return sum(x);
    int p,q;
    for(int i=1;i<=prCnt;i++) if(k%pr[i]==0) {p=pr[i]; break;}
    q=k; while(q%p==0) q/=p;
    getG[x_k]=true;
    int r=g(x,q)+g(x/p,k);
    return g1[x_k]=r;
}
int main()
{
    scanf("%d%d%d",&n,&m,&k);
    int n0=min(n,m);
    initF(); initG(2e6);
    long long ans=0;
    for(int L=1,R;L<=n0;L=R+1)
    {
        int v1=n/L,v2=m/L; R=min(n/v1,m/v2);
        ans+=1LL*(g(R,k)-g(L-1,k))*v1*f(v2);
    }
    printf("%lld\n",ans);
    return 0;
}

P.S.

本题中\(n,m\)的意义不等价,不可以互换...我以前为了简洁经常是用swap钦定\(n<m\),结果这题鸽了一周看不出来锅...

转载于:https://www.cnblogs.com/VisJiao/p/LOJ2085.html

内容概要:文章以“智能网页数据标注工具”为例,深入探讨了谷歌浏览器扩展在毕业设计中的实战应用。通过开发具备实体识别、情感分类等功能的浏览器扩展,学生能够融合前端开发、自然语言处理(NLP)、本地存储与模型推理等技术,实现高效的网页数据标注系统。文中详细解析了扩展的技术架构,涵盖Manifest V3配置、内容脚本与Service Worker协作、TensorFlow.js模型在浏览器端的轻量化部署与推理流程,并提供了核心代码实现,包括文本选择、标注工具栏动态生成、高亮显示及模型预测功能。同时展望了多模态标注、主动学习与边缘计算协同等未来发展方向。; 适合人群:具备前端开发基础、熟悉JavaScript和浏览器机制,有一定AI模型应用经验的计算机相关专业本科生或研究生,尤其适合将浏览器扩展与人工智能结合进行毕业设计的学生。; 使用场景及目标:①掌握浏览器扩展开发全流程,理解内容脚本、Service Worker与弹出页的通信机制;②实现在浏览器端运行轻量级AI模型(如NER、情感分析)的技术方案;③构建可用于真实场景的数据标注工具,提升标注效率并探索主动学习、协同标注等智能化功能。; 阅读建议:建议结合代码实例搭建开发环境,逐步实现标注功能并集成本地模型推理。重点关注模型轻量化、内存管理与DOM操作的稳定性,在实践中理解浏览器扩展的安全机制与性能优化策略。
基于Gin+GORM+Casbin+Vue.js的权限管理系统是一个采用前后端分离架构的企业级权限管理解决方案,专为软件工程和计算机科学专业的毕业设计项目开发。该系统基于Go语言构建后端服务,结合Vue.js前端框架,实现了完整的权限控制和管理功能,适用于各类需要精细化权限管理的应用场景。 系统后端采用Gin作为Web框架,提供高性能的HTTP服务;使用GORM作为ORM框架,简化数据库操作;集成Casbin实现灵活的权限控制模型。前端基于vue-element-admin模板开发,提供现代化的用户界面和交互体验。系统采用分层架构和模块化设计,确保代码的可维护性和可扩展性。 主要功能包括用户管理、角色管理、权限管理、菜单管理、操作日志等核心模块。用户管理模块支持用户信息的增删改查和状态管理;角色管理模块允许定义不同角色并分配相应权限;权限管理模块基于Casbin实现细粒度的访问控制;菜单管理模块动态生成前端导航菜单;操作日志模块记录系统关键操作,便于审计和追踪。 技术栈方面,后端使用Go语言开发,结合Gin、GORM、Casbin等成熟框架;前端使用Vue.js、Element UI等现代前端技术;数据库支持MySQL、PostgreSQL等主流关系型数据库;采用RESTful API设计规范,确保前后端通信的标准化。系统还应用了单例模式、工厂模式、依赖注入等设计模式,提升代码质量和可测试性。 该权限管理系统适用于企业管理系统、内部办公平台、多租户SaaS应用等需要复杂权限控制的场景。作为毕业设计项目,它提供了完整的源码和论文文档,帮助学生深入理解前后端分离架构、权限控制原理、现代Web开发技术等关键知识点。系统设计规范,代码结构清晰,注释完整,非常适合作为计算机相关专业的毕业设计参考或实际项目开发的基础框架。 资源包含完整的系统源码、数据库设计文档、部署说明和毕
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值