(待更)[学习笔记]数论例题选做1

你来迟了…
当你看到篇博客的时候,这个世界已经发生了翻天覆地的变化。
好吧其实就是开学了
这是寒假集训的最后一篇学习笔记了。
当然前面有两篇blog被我咕掉了,之后应该会咕回来的。
题目选自[集训小记]2020寒假集训(1.19-1.22)day4 数论部分。

1.BZOJ 4173 数学

欧拉函数

在这里插入图片描述
n , m ≤ 1 0 15 n,m\leq 10^{15} n,m1015

比较简单的题目。
S ( n , m ) S(n,m) S(n,m)这个集合的条件很不好处理,因此我们需要化简一下。
m m o d    k + n m o d    k ≥ k m − k × ⌊ m k ⌋ + n − k × ⌊ n k ⌋ ≥ k m + n ≥ k ∗ ( 1 + k × ⌊ m k ⌋ + k × ⌊ n k ⌋ ) ⌊ m + n k ⌋ ≥ 1 + ⌊ m k ⌋ + ⌊ n k ⌋ ⌊ m + n k ⌋ − ⌊ m k ⌋ − ⌊ n k ⌋ = 1 ⌊ m + n k ⌋ φ ( k ) − ⌊ m k ⌋ φ ( k ) − ⌊ n k ⌋ φ ( k ) = φ ( k ) m\mod k+n\mod k≥k\\ m-k\times \lfloor \frac{m}{k}\rfloor+n-k\times \lfloor \frac{n}{k}\rfloor≥k\\ m+n≥k*(1+k\times \lfloor \frac{m}{k}\rfloor+k\times \lfloor \frac{n}{k}\rfloor)\\ \lfloor \frac{m+n}{k}\rfloor≥1+\lfloor \frac{m}{k}\rfloor+\lfloor \frac{n}{k}\rfloor\\ \lfloor \frac{m+n}{k}\rfloor-\lfloor \frac{m}{k}\rfloor-\lfloor \frac{n}{k}\rfloor=1\\ \lfloor \frac{m+n}{k}\rfloorφ(k)-\lfloor \frac{m}{k}\rfloorφ(k)-\lfloor \frac{n}{k}\rfloorφ(k)=φ(k)\\ mmodk+nmodkkmk×km+nk×knkm+nk(1+k×km+k×kn)km+n1+km+knkm+nkmkn=1km+nφ(k)kmφ(k)knφ(k)=φ(k)
因此 ∑ k ∈ S ( n , m ) φ ( k ) = ∑ i = 1 n + m ⌊ m + n k ⌋ φ ( k ) − ∑ i = 1 m ⌊ m k ⌋ φ ( k ) − ∑ i = 1 n ⌊ n k ⌋ φ ( k ) \sum_{k\in S(n,m)}φ(k)=\sum^{n+m}_{i=1}\lfloor \frac{m+n}{k}\rfloorφ(k)-\sum^{m}_{i=1}\lfloor \frac{m}{k}\rfloorφ(k)-\sum^{n}_{i=1}\lfloor \frac{n}{k}\rfloorφ(k) kS(n,m)φ(k)=i=1n+mkm+nφ(k)i=1mkmφ(k)i=1nknφ(k)
为什么要这样做呢…因为 ∑ k = 1 n i = ∑ k = 1 n ∑ d ∣ k φ ( d ) = ∑ d = 1 n ⌊ n d ⌋ φ ( d ) \sum^n_{k=1}i=\sum^n_{k=1}\sum_{d|k}φ(d)=\sum^n_{d=1}\lfloor \frac{n}{d}\rfloorφ(d) k=1ni=k=1ndkφ(d)=d=1ndnφ(d)
然后答案就是 φ ( n ) ⋅ φ ( m ) n m φ(n)·φ(m)nm φ(n)φ(m)nm

/*Lower_Rating*/
/*number theory*/
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<stack>
#include<vector>
#include<queue>
#include<bitset>
#include<map>
using namespace std;

#define LL unsigned long long
#define DB double
#define MOD 998244353
#define Pr pair<int,int>
#define X first
#define Y second
#define MAXN 200000
#define MAXK 8000
#define eps 1e-10
#define INF 4294967298LL
#define mem(x,p) memset(x,p,sizeof(x))

LL read(){
  LL x=0,F=1;char c=getchar();
  while(c<'0'||c>'9'){if(c=='-')F=-1;c=getchar();}
  while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+c-'0';c=getchar();}
  return x*F;
}
inline int add(register int a,register int b){return (a+b>=MOD)?a+b-MOD:a+b;}
inline int dec(register int a,register int b){return (a-b<0)?a-b+MOD:a-b;}
inline int mul(register LL a,register int b){a*=b;return (a>=MOD)?a%MOD:a;}
inline int fst_pow(register int a,register int b){
    int res=1;
    while(b){
        if(b&1)res=mul(res,a);
        a=mul(a,a);
        b>>=1;
    }return res;
}
inline int inv(register int a){return fst_pow(a,MOD-2);}

int phi(LL x){
    int res=1;
    for(LL i=2;i*i<=x;i++)
    if(x%i==0){
        x/=i;res=mul(res,i-1);
        while(x%i==0)
        x/=i,res=mul(res,i);
    }
    if(x!=1)res=mul(res,(x-1)%MOD);
    return res;
}
LL n,m;
int main()
{
    n=read(),m=read();
    printf("%d",mul(mul(phi(n),phi(m)),mul(n%MOD,m%MOD)));
}

2.[51nod 1479]小Y的数论题

小Y喜欢研究数论,并且喜欢提一些奇怪的问题。
这天他找了三个两两互质的数 a , b , c a, b, c a,b,c,以及另一个数 m m m, 现在他希望找到三个 ( 0 , m ) (0, m) (0,m)范围内的整数 x , y , z x, y, z x,y,z,使得 ( x a + y b ) m o d    m = ( z c ) m o d    m (x^a+y^b)\mod m=(z^c) \mod m (xa+yb)modm=(zc)modm

构造题就要从最简单的方向想起。
我们知道 2 t + 2 t = 2 t + 1 2^t+2^t=2^{t+1} 2t+2t=2t+1,显然我们可以从这里入手。
首先我们先构造 ( 2 a k ) b + ( 2 b k ) a = 2 k a b + 1 (2^{ak})^{b}+(2^{bk})^a=2^{kab+1} (2ak)b+(2bk)a=2kab+1
这样我们就只用满足 z c z^c zc这一项了。
z = 2 l z=2^l z=2l,那么就有 k ⋅ a ⋅ b − c ⋅ l = 1 k·a·b-c·l=1 kabcl=1
显然我们可以直接用exgcd解决。
有个大坑,原题要求我们 x , y , z x,y,z x,y,z要在 ( 0 , m ) (0,m) (0,m)之间,当 m = 2 t m=2^t m=2t时,我们的解中可能会有零。
所以我们需要单独构造…
[讲个笑话,我开着ull调了半天]

/*Lower_Rating*/
/*number theory*/
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<stack>
#include<vector>
#include<queue>
#include<bitset>
#include<map>
using namespace std;

#define LL long long
#define DB double
#define MOD 998244353
#define Pr pair<int,int>
#define X first
#define Y second
#define MAXN 200000
#define MAXK 8000
#define eps 1e-10
#define INF 4294967298LL
#define mem(x,p) memset(x,p,sizeof(x))

LL read(){
  LL x=0,F=1;char c=getchar();
  while(c<'0'||c>'9'){if(c=='-')F=-1;c=getchar();}
  while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+c-'0';c=getchar();}
  return x*F;
}
inline int add(register int a,register int b){return (a+b>=MOD)?a+b-MOD:a+b;}
inline int dec(register int a,register int b){return (a-b<0)?a-b+MOD:a-b;}
inline int mul(register LL a,register int b){a*=b;return (a>=MOD)?a%MOD:a;}

int T;
LL m,a,b,c;
LL exgcd(LL a,LL b,LL &X,LL &Y){
    if(b==0){X=1,Y=0;return a;}
    LL x0,y0,G;
    G=exgcd(b,a%b,x0,y0);
    X=y0,Y=x0-(a/b)*y0;
    return G;
}
LL fst_pow(LL a,LL b){
    LL res=1;
    while(b){
        if(b&1)res=1LL*res*a%m;
        a=1LL*a*a%m;
        b>>=1;
    }return res;
}
int main()
{
    T=read();
    while(T--){
        m=read();
        a=read(),b=read(),c=read();
        LL k,l;
        if(m&(m-1)){
            exgcd(a*b,c,k,l),k=-k;
            while(k<0||l<0)k+=c,l+=a*b;
            printf("%lld %lld %lld\n",fst_pow(2,k*b),fst_pow(2,k*a),fst_pow(2,l));
        }else{
            if(a>1)printf("%d %d %d\n",m/2,1,1);
            else if(b>1)printf("%d %d %d\n",1,m/2,1);
            else if(c>1)printf("%d %d %d\n",m/2,m/2,m/2);
            else printf("%d %d %d\n",1,1,2);
        }
    }
}

3.[51nod1245] Binomial Coefficients Revenge

给出 M M M和质数 p p p,求 ( 0 M ) , ( 1 M ) . . . . . . ( M M ) \binom{0}{M}, \binom{1}{M}......\binom{M}{M} (M0),(M1)......(MM) M + 1 M + 1 M+1个数中,有多少数不是 p p p的倍数,有多少是 p p p的倍数但不是 p 2 p^2 p2的倍数,有多少是 p 2 p^2 p2的倍数但不是 p 3 p^3 p3的倍数…。
1 ≤ T ≤ 5000 , 2 ≤   M , P ≤ 1 0 18 1 \leq T \leq 5000,2\leq\ M,P \leq10^{18} 1T5000,2 M,P1018

这题的关键就是库默尔定理吧…
我们都知道质数 p p p n ! n! n!出现次数是 ∑ i = 1 n ⌊ n p i ⌋ \sum^n_{i=1}\lfloor \frac{n}{p^i}\rfloor i=1npin
组合数 ( m n ) \binom{m}{n} (nm)的贡献就是 ∑ i = 1 n ⌊ n p i ⌋ − ⌊ m p i ⌋ − ⌊ n − m p i ⌋ \sum^n_{i=1}\lfloor \frac{n}{p^i}\rfloor-\lfloor \frac{m}{p^i}\rfloor-\lfloor \frac{n-m}{p^i}\rfloor i=1npinpimpinm
根据第1题的结论,我们知道 ⌊ n p i ⌋ − ⌊ m p i ⌋ − ⌊ n − m p i ⌋ \lfloor \frac{n}{p^i}\rfloor-\lfloor \frac{m}{p^i}\rfloor-\lfloor \frac{n-m}{p^i}\rfloor pinpimpinm只能为1或者0。
根据库默尔定理有 n m o d    p i + 1 < m m o d    p i + 1 n\mod p^{i+1}<m\mod p^{i+1} nmodpi+1<mmodpi+1时取到1。
因此我们将 n n n看成 p p p进制下的数,那么我们统计 n n n的后缀小于 m m m的后缀的次数就行了。
所以我们直接数位dp,令 d p [ i ] [ j ] [ 0 / 1 ] dp[i][j][0/1] dp[i][j][0/1]为当前是从低到高第 i i i位,现在已经有 j j j次取到1,上一次是否取到1(因为这一次是否取到和上一次是否取到1有关系) m m m的个数。
由于 m ≤ n m\leq n mn,所以我们最终只需输出 d p [ e n d ] [ i ] [ 0 ] dp[end][i][0] dp[end][i][0]( e n d end end为最后一位)就好了。
复杂度: O ( T ⋅ l o g P 2 M ) O(T·log^2_{P}M) O(TlogP2M)

/*Lower_Rating*/
/*number theory*/
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<stack>
#include<vector>
#include<queue>
#include<bitset>
#include<map>
using namespace std;

#define LL long long
#define DB double
#define MOD 998244353
#define Pr pair<int,int>
#define X first
#define Y second
#define MAXN 100
#define MAXK 8000
#define eps 1e-10
#define INF 4294967298LL
#define mem(x,p) memset(x,p,sizeof(x))

LL read(){
  LL x=0,F=1;char c=getchar();
  while(c<'0'||c>'9'){if(c=='-')F=-1;c=getchar();}
  while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+c-'0';c=getchar();}
  return x*F;
}
inline int add(register int a,register int b){return (a+b>=MOD)?a+b-MOD:a+b;}
inline int dec(register int a,register int b){return (a-b<0)?a-b+MOD:a-b;}
inline int mul(register LL a,register int b){a*=b;return (a>=MOD)?a%MOD:a;}

int T;
LL n,p,a[MAXN+5];int m;
LL dp[MAXN+5][MAXN+5][2];
int main()
{
    T=read();
    while(T--){
        mem(dp,0);
        m=0,n=read(),p=read();
        LL x=n;
        while(x)a[++m]=x%p,x/=p;
        dp[1][1][1]=p-a[1]-1,dp[1][0][0]=a[1]+1;
        for(int i=2;i<=m;i++)
            for(int j=0;j<i;j++){
                dp[i][j][0]=(a[i]+1)*dp[i-1][j][0]+a[i]*dp[i-1][j][1];
                dp[i][j+1][1]=(p-a[i]-1)*dp[i-1][j][0]+(p-a[i])*dp[i-1][j][1];
            }
        for(int i=0;i<=m&&dp[m][i][0];i++)
        printf("%lld ",dp[m][i][0]);
        puts("");
    }
}

4.[51nod 1132]覆盖数字的数量V2

给出 2 2 2个整数 A A A B B B。可以使用任意次。再给出一段从 X − Y X - Y XY的区间T,任选若干个 A A A B B B做加法,可以覆盖区间T中多少个不同的整数。

对不起,它被咕了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值