数学数论专项练习 day 60

link

A

显然只需要考虑质因子。

首先 k 只有一个质因子可以特判,有两个可以 exgcd

有三个及其以上那么最小的一个 105,同余最短路即可。

B

考虑一个序列 {x|x=aibit,tN},对于一个质因子提出了怎样的限制?

ai,bi 在质因数 p 的指数分别是 ci,p,di,p

则 Ans 设为 piri

必然有对于每个 p,有:

  1. i,ci,prp

  2. i,rpci,p(moddi,p)

  3. k,p,rp=ci,p+k·di,p

    也就是要求 b 的指数相同

    等价于:

    p1,p2,i,di,p>0,rp1ci,p1di,p1=rp2ci,p2di,p2

限制条件 2 应当是可解的,会得到一个 rphp(modmp),限制条件 1 可以通过调整下界来满足

但是限制条件 3 就有一点那个

其实可以通过 hp,mp 来反过来对 aibiki 中的 ki 提出限制。

类如 kixi(modti) 这种东西,其实也就是最初的 hp 给出的限制,还有后面的 mp 给出的限制,这是一个 p 给一个序列的限制,一个序列的 k 可以由这些线性同余方程组解出来

解出来之后呢,由于每个 ki 是独立的,但是我们要求最终的解答是一样的,所以每个 ki 可以通过质因子建立一些关系,这显然也是丢番图方程

嗯貌似可以高斯消元

然后取一组最小的解出来就好了

太TMD扯淡了这个题写起来

n100?

C

硬算指定死,不过因为 C106,所以可以处理出两个区间每个数字的出现次数,这可以暴力找循环节。注意循环节前面还有一段未进入循环节的部分

而且有 pq+qp 由于呈现倒数关系所以值最大是 C+1

考虑设 f(x,y)=xy+yx,考虑求解 [f(xi,yi)k]

考虑到这玩意是对勾函数,那么对于一个 xi 而言是可以利用二次函数解出一段区间的

现在还是 O(C2),考虑优化

注意到对勾函数存在分界点,也就是 x=y 的时候,不妨钦定 x<y,枚举 x,则这个对勾函数随着 y 增加而增加,最多取到 Cy,所以是调和级数复杂度。

D

首先 gcdai 的肯定是解,然后根据欧拉定理显然不存在大于 n 的质数符合条件了

那么考虑枚举 n 的质数,利用欧拉定理将其变为 p1 阶多项式后判断系数模 p 是否是全零,同时需要有 p|a0

这东西疑似充要

E

拜谢粉方方,粉方方好闪

显然可以等效为 aFibn+bFibn+10(modm)

自然地除掉 gcd(a,b,m) 同时 b 进行移项,变为 a,b,m,则有:

aFibnbFibn+1(modm),gcd(a,b,m)=1

也就相当于 aFibn=bFibn+1+km

同时除掉 gcd(a,m) 显然也成立,这就要求 gcd(a,m)|bFibn+1,gcd(a,b,m)=1gcd(a,m)|Fibn+1

类似地,也可以得出 gcd(b,m)|Fibn,又因为有 gcd(Fibn,Fibn+1)=1,所以类似有 gcd(Fibn,m)|b,gcd(Fibn+1,m)|a

则有:gcd(Fibn+1,m)|a,gcd(a,m)|Fibn+1gcd(Fibn+1,m)=gcd(a,Fibn+1,m)

类似地可以有 gcd(Fibn+1,m)=gcd(a,m)

也有 gcd(Fibn,m)=gcd(b,m)

不妨设 x=gcd(Fibn,m),y=gcd(Fibn+1,m)

则显然有 gcd(x,y)=1,且 (xy)|m,y|(aFibn),x|(bFibn+1)

所以给原同余式整体除掉 xy 是可以的,且除掉之后所有数字就互质了

互质就可以求逆元了,同时也说明了 (ay,bx,mxy)(Fibn+1x,Fibny,mxy) 是对应的,因为可以互推。

注意到后面的三元组个数与 m 的约数和同阶(显然 Fib 数列循环节长度与模数同阶,手玩易证)

可以暴力处理出来直接哈希表/map 回答询问即可。

F

显然你三个方向两个向外一个向内,所以向外的状态向向内的状态连边,则可以变成一颗二叉树,而原题等价于问两个点之间的距离,显然我们只需要求出 deplca 即可。

可以考虑倍增,显然我们可以在类似辗转相除法地计算 k 级祖先,这就好了

G

妙啊,是我不会的题

首先由于 n2,故可以考虑 CRT,设 ij,x=a+bi+ki(c+di)=a+bj+kj(c+dj)

可以得出 b(ij)=(kjki)c+(jkjiki)d

由于 ij 是可以任意取的,譬如取 1,而根据裴属定理,后面显然可以给出 gcd(c,d)|b,当然也因为后面不为零

这是一个判断无解的条件

那么我们设 g=gcd(b,c,d)=gcd(c,d)

一步很妙的就是拿出常数 a 将其变为 amodg,a(amodg),这一步即使在同余意义下也当然是对的,可以考虑暴力Excrt最终合并后的式子,a 不影响。

那么就可以令 a=ag,b=bg,c=cg,d=dg

我们求解 xa+bi(modc+di),i[0,n1]Z

则答案可以还原为 x=xg+(amodg)

这是因为你给Excrt过程中的每个 Mi(c+di) 除掉了因子 g,则你乘回去对于每个式子仍然成立(写成不定方程就方便多了)。

则有:

xa+bi(modc+di)dxda+dbi(modc+di)dxda+b(c+di)cb(modc+di)dxdacb(modc+di)

可以看到我们利用乘法手段将整个同余式右侧化成了定值,则满足如上式子等价于满足 M=lcm(c+di),dxdacb(modM)

我们所需最小非负整数解 x,则也即只需要求得一个 d|(dacb+yM) 满足 dacb+yM0 的第一个符合要求的值。

显然我们只需要枚举一个循环节,也就是 d 个连续整数的 y

我们可以进行如下处理:

  • dacb<0

    • M 极大时(严格意义上讲 |dacb| 即可,为了方便编程不妨设 inf=2e12

    我们可以枚举 [1,d] 以内的整数作为 y 计算答案

    • M 较小时,直接对 dacb 取模 M 的最小非负值(这时候 M 是可以存下的)
  • dacb0

    • M 极大时,我们可以枚举 [0,d1] 的整数作为 y
    • M 较小时,我们先取 dacb 取模 M 的最小非负值,然后枚举 [0,d1] 的整数作为 y

这样的枚举策略显然可以保证有解就可以找到一组最小的合法解。

最后我们求出 dacb+yM998244353 的值之后,再求 d 在模 998244353 意义下的逆元,计算答案即可。

那么问题就只剩下三个

  1. 求解 Md 的值
  2. 求解 M998244353 的值
  3. 判断 M 是否的“极大的”

不妨设 wi=c+di

注意到 gcd(wi,wj)=gcd(c+di,(ij)d),可以有 gcd(wi,wj)|(ij)d

同时由于 gcd(c,d)=1,而 gcd(wi,d)=gcd(c,d)=1,所以说 gcd(wi,wj,d)=1,也就是 gcd(wi,wj)d 互质。

那么可以得到 gcd(wi,wj)|(ij),而 ij<n,所以不同 w 之间的共同质因子必然是 [2,n]Z 的质数。

所以我们筛掉 n 以内的质数(w 除掉相应质数)后,w 之间两两互质。

在这一步里,M 就可以拆分为每个 n 以内的质数的最大次幂以及除掉这些质数后余下的 w 的积。

至于筛掉质数这一步,不妨枚举 p,也就是要求所有的 i 满足 c+di0(modp)di+pj=c,可以利用 exgcd 求出 i 的通解进行暴力计算最大次幂和除法。

这一步的复杂度是不超过 O(nlogn+nlogd) 的,这是因为

  1. gcd(d,p)1 时,pd 的质因子,此时 gcd(d,p)=pi 的循环节长度是 1

    这样的 p 只有不超过 logd

  2. gcd(d,p)=1 时,i 的循环节长度是 p,也就是有 np 个,根据调和级数的知识这必然不超过 O(nlogn)

通过这一步筛除质数后乘上所有剩下的 w 就可以计算出 Md 和 模 998244353 的值了,至于是否是极大的,在乘法过程中判断即可。

实现:

#include<bits/stdc++.h>
using namespace std;
#define int long long 
const int inf=2e12,mod=998244353;
int Md=1,Mans=1,Mup=1,N,A,B,C,D;
int w[1050050],v[1050500];
int exgcd(int a,int b,int &x,int &y){
    if(!b){
        x=1,y=0;return a;
    }
    int d=exgcd(b,a%b,x,y);
    int z=x;x=y,y=z-(a/b)*y;
    return d;
}
signed main(){
    // ios::sync_with_stdio(false);
    cin>>N>>A>>B>>C>>D;
    int g=__gcd(C,D);if(B%g){
        cout<<"-1\n";return 0;
    }
    int SurA=A%g;A/=g;B/=g,C/=g,D/=g;
    for(int i=0;i<N;++i)w[i]=C+D*i;
    for(int i=2;i<=N;++i){
        if(!v[i]){
            int p=i;
            for(int j=i;j<=N;j+=i)v[j]=1;
            //x*p+y*d=-c
            if(C%__gcd(p,D))continue;
            int x,y;int d=exgcd(p,D,x,y);
            int len=p/d;y=y*(-(C/d)%len)%len;
            y=(y%len+len)%len;
            int mx=0;
            // cout<<p<<": ";
            for(int k=y;k<N;k+=len){
                int c=0;
                // cout<<k<<" "<<C+D*k<<"\n";
                while(w[k]%p==0)w[k]/=p,++c;
                mx=max(mx,c);
            }
            while(mx--){
                Md=Md*p%D;
                Mans=Mans*p%mod;
                if(Mup>inf/p)Mup=inf+1;
                else Mup=min(Mup*p,inf+1);
            }
        }
    }
    for(int i=0;i<N;++i)if(w[i]>1){
        Md=Md*(w[i]%D)%D;
        Mans=Mans*(w[i]%mod)%mod;
        if(Mup>inf/w[i])Mup=inf+1;
        else Mup=min(Mup*w[i],inf+1);      
        // cout<<w[i]<<" "<<i<<"\n";
    }
    // cout<<"prepared\n";
    Mup=min(Mup,inf+1);
    int tmp=A*D-B*C;
    if(Mup!=inf+1)tmp=(tmp%Mup+Mup)%Mup;
    auto power=[&](int a,int b)->int{
        a%=mod;
        int ans=1;
        while(b){
            if(b&1)ans=ans*a%mod;
            a=a*a%mod;b>>=1;
        }
        return ans;
    };
    // cout<<"pw "<<" "<<Md<<" "<<Mup<<' '<<Mans<<"\n";
    for(int y=0;y<=D;++y){
        // cout<<y<<"\n";
        if(tmp<0&&y==0)continue;
        if((tmp+y*Md%D)%D)continue;
        // cout<<"Find\n";
        int ans=(y*(Mans%mod)+tmp%mod)%mod;
        ans=ans*power(D,mod-2)%mod;
        ans=ans*g%mod;
        ans=(ans+SurA)%mod;
        cout<<ans<<"\n";return 0;  
    }
    cout<<"-1\n";
    return 0;
}
posted @   spdarkle  阅读(9)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示