cogs 2405 [noi2016]循环之美 杜教筛+DP

本文提出一个关于最简分数在特定进制下纯循环条件的推论,并给出详细证明。随后利用该结论解决一类数论问题,通过引入莫比乌斯函数和杜教筛等工具进行高效计算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

标签(空格分隔): 数论


题目链接1
题目链接2
题目链接3
一个推论:
一个最简分数\(\frac{x}{y}\)在k进制下是纯循环的,当且仅当\(\gcd(y,k)=1\)
证明:
不妨设\(x\leq y\)。最简分数即\(\gcd(x,y)=1\)。纯循环即小数位的第1位属于循环节,那么就是存在p满足\(x\equiv x\times k^p \pmod y\)即余数出现循环是从小数点对应第一位的余数开始的。
由于\((x,y)=1\),所以当且仅当存在p使\(1 \equiv k^p \pmod y\),那么\(\frac{x}{y}\)就是纯循环的。
而这个结论成立当且仅当\((k,y)=1\),所以得证。

有了这个推论,我们要求的式子一目了然:
\[ \sum_{i=1}^{n}\sum_{j=1}^{m}[(i,j)=1]\cdot[(j,k)=1] \]
然后就是数学式子的推导了。我尽可能写的在清晰的情况下易懂。
\[ \begin{eqnarray*} ans & = & \sum_{i=1}^n\sum_{j=1}^m[(i,j)=1]\cdot[(j,k)=1]\\ & = & \sum_{i=1}^n\sum_{j=1}^m\sum_{d|i,d|j}{\mu(d)}\cdot[(j,k)=1]\\ & = & \sum_{d=1}^{min(n,m)}\mu(d)\cdot\left\lfloor\frac{n}{d}\right\rfloor\sum_{j=1}^{m}[d|j]\cdot[(j,k)=1]\\ & = & \sum_{d=1}^{min(n,m)}\mu(d)\cdot\left\lfloor\frac{n}{d}\right\rfloor\sum_{j=1}^{\left\lfloor\frac{m}{d}\right\rfloor}[(jd,k)=1]\\ & = & \sum_{d=1}^{min(n,m)}[(d,k)=1]\cdot\mu(d)\left\lfloor\frac{n}{d}\right\rfloor\sum_{j=1}^{\left\lfloor\frac{m}{d}\right\rfloor}[(j,k)=1]\\ \end{eqnarray*} \]
\(f(n)=\sum_{i=1}^{n}[(i,k)=1]\)
根据\(\gcd(a,b)=\gcd(a+b,b)=\gcd(a+kb,b)\),我们可以知道\(f(n)=\left\lfloor\frac{n}{k}\right\rfloor\cdot f(k) + f(n\bmod k)\),所以\(f\)函数预处理\(O(k\log k)\),查询\(O(1)\)
\[ \begin{align} ans = \sum_{d=1}^{min(n,m)}[(d,k)=1]\cdot\mu(d)\left\lfloor\frac{n}{d}\right\rfloor f\left(\left\lfloor\frac{m}{d}\right\rfloor\right) \\ \end{align} \]
\(S(n)=\sum_{i=1}^{n}[(i,k)=1]\cdot \mu(i)\),考虑通过类似洲阁筛的DP求出\(S\)
定义\(s(i,n)\)表示小于等于\(n\)且与\(k\)的前\(i\)种质因子互质的数\(d\)\(\mu(d)\)之和,初始化\(s(i,n)=\sum_{d=1}^{n}\mu(d)\),用杜教筛即可。
\[ s(i,n)=s(i-1,n)-\mu(p_i)\cdot s(i,\left\lfloor\frac{n}{p_i}\right\rfloor) \]
还是比较好理解的。意思就是从与前\(i-1\)互质的所有\(\mu\)中减去不与\(i\)互质的。由于\(\mu\)不是完全积性函数,所以要求除去\(p_i\)后与前i互质而不是与前\(i-1\)互质,因此要注意第二维转移应是递增转移。

根据\((1)\)式可得,\(s(i,n)\)函数的第二维只有\(O(\sqrt{n}+\sqrt{m})\)种取值,所以DP的复杂度是预处理\(O(n^{\frac{2}{3}})\)+DP\(O(w(k)\cdot (\sqrt{n}+\sqrt{m}))\)(\(w(k)\)表示k的不同质因子个数,由于\(k\leq 2000\),\(w(k)\)最大也就是\(4\)),也是本题最终复杂度。

code

#include<stdio.h>
#include<set>
#include<map>
#include<algorithm>
#include<math.h>
using namespace std;
typedef long long LL;
int n,m,K,maxn;
int mu[1000010];
bool flag[1000010];
int prime[500010],tot=0;
void Init(){
    mu[1]=1;
    for(int i=2;i<=maxn;++i){
        if(!flag[i]){
            prime[++tot]=i;
            mu[i]=-1;
        }
        for(int j=1;j<=tot&&i*prime[j]<=maxn;++j){
            flag[i*prime[j]]=true;
            if(i%prime[j]==0) break;
            mu[i*prime[j]]=-mu[i];
        }
    }
    for(int i=1;i<=maxn;++i) mu[i]+=mu[i-1];
}
map<int,int> M;
int Gcd(int a,int b){return b==0?a:Gcd(b,a%b);}
int Mu(int x){
    if(x<=maxn) return mu[x];
    if(M.count(x)) return M[x];
    int ans=0;
    for(int i=2,j;i<=x;i=j+1){
        j=x/(x/i);
        ans+=(j-i+1)*Mu(x/i);
    }
    M[x]=1-ans;
    return 1-ans;
}
#define R(x) (x<=sqr?x:cnt-(n/x)+1)
int H[120010],cnt;
map<int,int> R;
set<int> P;
int p[10],tmp,F[2010];
inline int f(int x){return (x/K)*F[K]+F[x%K];}
int S[120010];
int main(){
    freopen("cyclic.in","r",stdin);
    freopen("cyclic.out","w",stdout);
    
    scanf("%d%d%d",&n,&m,&K);
    maxn=(int)pow(n,2.0/3.0);
    Init();
    
    for(int i=1;i*i<=n;++i) P.insert(i),P.insert(n/i);
    for(int i=1;i*i<=m;++i){
        if(i<=n) P.insert(i);
        if(m/i<=n) P.insert(m/i);
    }
    for(set<int>::iterator iter=P.begin();iter!=P.end();++iter){
        R[*iter]=++cnt;
        H[cnt]=*iter;
    }
    for(int i=1;i<=cnt;++i) S[i]=Mu(H[i]);
    for(int i=1;i<=K;++i) F[i]=F[i-1]+(Gcd(i,K)==1);
    int x=K;
    for(int i=2;i*i<=x;++i){
        if(x%i==0){
            p[++tmp]=i;
            while(x%i==0) x/=i;
        }
    }
    if(x>1) p[++tmp]=x;
    for(int i=1;i<=tmp;++i){
        for(int j=1;j<=cnt;++j){
            if(H[j]<p[i]) continue;
            S[j]+=S[R[H[j]/p[i]]];
        }
    }
    LL Last=0,Now,ans=0;
    for(int i=1,j,y=min(n,m);i<=y;i=j+1){
        j=min(n/(n/i),m/(m/i));
        Now=S[R[j]];
        ans+=(LL)(Now-Last)*(n/i)*f(m/i);
        Last=Now;
    }
    printf("%lld\n",ans);
    getchar(); getchar();
    fclose(stdin); fclose(stdout);
    return 0;
}

转载于:https://www.cnblogs.com/kito/p/7009060.html

内容概要:本文针对国内加密货币市场预测研究较少的现状,采用BP神经网络构建了CCi30指数预测模型。研究选取2018年3月1日至2019年3月26日共391天的数据作为样本,通过“试凑法”确定最优隐结点数目,建立三层BP神经网络模型对CCi30指数收盘价进行预测。论文详细介绍了数据预处理、模型构建、训练及评估过程,包括数据归一化、特征工程、模型架构设计(如输入层、隐藏层、输出层)、模型编译与训练、模型评估(如RMSE、MAE计算)以及结果可视化。研究表明,该模型在短期内能较准确地预测指数变化趋势。此外,文章还讨论了隐层节点数的优化方法及其对预测性能的影响,并提出了若干改进建议,如引入更多技术指标、优化模型架构、尝试其他时序模型等。 适合人群:对加密货币市场预测感兴趣的研究人员、投资者及具备一定编程基础的数据分析师。 使用场景及目标:①为加密货币市场投资者提供一种新的预测工具和方法;②帮助研究人员理解BP神经网络在时间序列预测中的应用;③为后续研究提供改进方向,如数据增强、模型优化、特征工程等。 其他说明:尽管该模型在短期内表现出良好的预测性能,但仍存在一定局限性,如样本量较小、未考虑外部因素影响等。因此,在实际应用中需谨慎对待模型预测结果,并结合其他分析工具共同决策。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值