IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 【解题报告】随便练练一(CF 2300) -> 正文阅读

[数据结构与算法]【解题报告】随便练练一(CF 2300)

A:The Child and Sequence | CF438D

题意

  • 长度为 n n n 的序列 a n a_n an?,你需要实现如下共 m m m 次操作:
    (1)求区间和
    (2)区间取模 x x x
    (3)单点置 a k = x a_k=x ak?=x
  • 1 ≤ n , m ≤ 1 0 5 1\le n,m\le 10^5 1n,m105
    1 ≤ a i ≤ 1 0 9 1\le a_i\le 10^9 1ai?109

思路

  • 关键是区间取模怎么做,貌似是一个挺经典的题了。
    考虑,对于一个数 x x x,每次取模,这个数字最大变为 x 2 \frac{x}{2} 2x?,所以最多取模次数是 O ( log ? ) O(\log ) O(log) 级别的
  • 如果区间的最大值 m x < x mx<x mx<x,那么区间取模 x x x 相当于没有取模。
    如上两个操作就可以保证复杂度。注意我们只有单点置没有区间置。

代码

  • 时间复杂度: O ( ( n + m ) log ? R ) O((n+m)\log R) O((n+m)logR)
#include<bits/stdc++.h>
using namespace std;
#define ls (p<<1)
#define rs (p<<1|1)
#define md ((l+r)>>1)
#define ll long long
const int MAX = 1e5+50;
ll aa[MAX];
ll treeSum[MAX*4];
ll treeMx[MAX*4];
void push_up(int p){
    treeSum[p]=treeSum[ls]+treeSum[rs];
    treeMx[p]=max(treeMx[ls],treeMx[rs]);
}
void build(int p,int l,int r){
    if(l == r){
        treeSum[p] = treeMx[p] = aa[l];
        return;
    }
    build(ls,l,md);
    build(rs,md+1,r);
    push_up(p);
}
void update(int p,int l,int r,int u,ll k){
    if(l == r){
        treeSum[p] = treeMx[p] = k;
        return;
    }
    if(u <= md)update(ls,l,md,u,k);
    if(u >  md)update(rs,md+1,r,u,k);
    push_up(p);
}
void update2(int p,int l,int r,int ux,int uy,ll k){
    if(treeMx[p] < k)return;
    if(l == r){
        treeSum[p] %= k;
        treeMx[p]  %= k;
        return;
    }
    if(ux <= md)update2(ls,l,md,ux,uy,k);
    if(uy >  md)update2(rs,md+1,r,ux,uy,k);
    push_up(p);
}
ll query(int p,int l,int r,int qx,int qy){
    ll res = 0;
    if(qx <= l && r <= qy)return treeSum[p];
    if(qx <= md)res += query(ls,l,md,qx,qy);
    if(qy >  md)res += query(rs,md+1,r,qx,qy);
    return res;
}
int main()
{
    int n,m;scanf("%d%d",&n,&m);
    for(int i = 1;i <= n;++i)scanf("%lld",&aa[i]);
    build(1,1,n);
    for(int i = 1;i <= m;++i){
        ll op,t1,t2,t3;
        scanf("%lld",&op);
        if(op == 1){
            scanf("%lld%lld",&t1,&t2);
            printf("%lld\n",query(1,1,n,t1,t2));
        }else if(op == 2){
            scanf("%lld%lld%lld",&t1,&t2,&t3);
            update2(1,1,n,t1,t2,t3);
        }else{
            scanf("%lld%lld",&t1,&t2);
            update(1,1,n,t1,t2);
        }
    }
    return 0;
}

B:Errich-Tac-Toe (Hard Version) | CF1450C2

题意

  • 给定一个大小为 n × n n\times n n×n 的网格,每个格子要么为空,要么为 X X X,要么为 O O O
    规定,出现赢局就是行 / 列上有同时有三个相同的 O O O 或者 X X X
    在这里插入图片描述
  • 一次操作,你可以翻转一个 X X X 变成 O O O 或者翻转一个 O O O 变成 X X X
    假设棋盘上有 k k k 个棋子,请在最多 ? k 3 ? \lfloor \frac{k}{3}\rfloor ?3k?? 步内让棋局没有赢局。
    1 ≤ n ≤ 300 1\le n\le 300 1n300
  • 你需要输出最后的没有赢局的局面。

思路

  • 感觉如果用各种奇妙的贪心和特判的话,这题会变得特别不好做。
    我们先考虑一下,如果一个局面全是 X X X 的话,怎么处理?

XXXXX
XXXXX
XXXXX
XXXXX
XXXXX

  |
  V

XXOXX
XOXXO
OXXOX
XXOXX
XOXXO

  • 可以依稀感觉到,对于 a x , y a_{x,y} ax,y? 的棋子,我们按 ( x + y ) % 3 (x+y)\%3 (x+y)%3 作为三个同余类 S 0 , S 1 , S 2 S_0,S_1,S_2 S0?,S1?,S2?去处理。
    如果我们定 S 0 S_0 S0? 必须为 X X X,这样就可以保证不会有 O O O 的赢局
    如果我们定 S 0 S_0 S0? 必须为 O O O,这样就可以保证不会有 X X X 的赢局
    我们不希望有 O O O X X X 的赢局,我们可以让 S 0 , S 1 , S 2 S_0,S_1,S_2 S0?,S1?,S2? 中的两项取出来,满足上述俩要求即可。
  • 接下来是操作上限的证明
    容易得到:
    S 0 ( X ) + S 1 ( X ) + S 2 ( X ) + S 0 ( O ) + S 1 ( O ) + S 2 ( O ) = k S_0(X)+S_1(X)+S_2(X)+S_0(O)+S_1(O)+S_2(O)=k S0?(X)+S1?(X)+S2?(X)+S0?(O)+S1?(O)+S2?(O)=k
    所以必定存在一对 S t ( X ) , S t + 1 ( O ) S_t(X),S_{t+1}(O) St?(X),St+1?(O),满足
    S t ( X ) + S t + 1 ( O ) ≤ ? k 3 ? S_t(X)+S_{t+1}(O)\le \lfloor \frac{k}{3} \rfloor St?(X)+St+1?(O)?3k??
    当然也存在 S t ( O ) , S t + 1 ( X ) S_t(O),S_{t+1}(X) St?(O),St+1?(X) 也是满足的。

代码

  • 时间复杂度: O ( n 2 ) O(n^2) O(n2)
#include<bits/stdc++.h>
using namespace std;
void show(){std::cerr << endl;}template<typename T,typename... Args>void show(T x,Args... args){std::cerr << "[ " << x <<  " ] , ";show(args...);}
#define ll long long
const int MAX = 3e2+50;

char aa[MAX][MAX];

int main()
{
    int T;scanf("%d",&T);
    while(T--){
        int n;scanf("%d",&n);
        int k = 0;
        for(int i = 1;i <= n;++i)scanf("%s",aa[i]+1);

        for(int i = 1;i <= n;++i)
        for(int j = 1;j <= n;++j)
            if(aa[i][j] != '.')k++;

        for(int t = 0;t < 3;++t){
            int cnt = 0;
            for(int i = 1;i <= n;++i)
            for(int j = 1;j <= n;++j){
                if((i+j)%3 == t && aa[i][j] == 'X')cnt++;
                if((i+j+1)%3 == t && aa[i][j] == 'O')cnt++;
            }
            if(cnt <= k / 3){
                for(int i = 1;i <= n;++i){
                    for(int j = 1;j <= n;++j){
                        if((i+j)%3 == t && aa[i][j] == 'X')aa[i][j] = 'O';
                        if((i+j+1)%3 == t && aa[i][j] == 'O')aa[i][j] = 'X';
                        printf("%c",aa[i][j]);
                    }
                    puts("");
                }
                break;
            }
        }
    }
    return 0;
}

C:Sonya and Problem Wihtout a Legend | CF713C

题意(在原题上增强)

思路

  • 这个题目一个是改为单调不递减,一个是改为严格单调递增,但其实是等价的。
    假设原数列元素有 a < b < c a<b<c a<b<c
    我们令 a a ≤ b b ≤ c c aa\le bb\le cc aabbcc
    其实就是相当于 a a < b b ? 1 < c c ? 2 aa<bb-1<cc-2 aa<bb?1<cc?2
    也相当于 a a ? 1 < b b ? 2 < c c ? 3 aa-1<bb-2<cc-3 aa?1<bb?2<cc?3
    所以,我们原序列中的元素 a i a_i ai? 更新为 a i = a i ? i a_i=a_i-i ai?=ai??i,那么严格单调递增问题就可以转化为单调不递减序列问题。
    注意到,我们问题之和 a i a_i ai? a j a_j aj? 的差值有关,而与 a i a_i ai? 的具体数值是无关的,因此可以转化。
  • 有一个比较简单的例子。假设 n = 2 n=2 n=2,有数字 a , b a,b a,b,其中 a > b a>b a>b
    这个时候,答案一定是 b ? a b-a b?a,方案也很简单,就是 c ∈ [ a , b ] c\in[a,b] c[a,b],然后让 a , b a,b a,b 都变成 c c c 即可。
    注意到,如果数列长度比较长,为了让答案不劣,我们令 c = a c=a c=a 明显是更优的。
  • 假设现在我们处理到 i i i 的答案了,其中 a i ? 1 a_{i-1} ai?1? 我们修改值变为了 a i ? 1 ′ a_{i-1}^\prime ai?1?
    如果 a i ≥ a i ? 1 ′ a_i\ge a_{i-1}^\prime ai?ai?1?,显然我们不需要修改。
    否则,我们需要多操作 a i ? 1 ′ ? a i a_{i-1}^\prime-a_i ai?1??ai? 次操作。
    ? \color{red}{*} ? 在形式上,我们可以令 a i ? 1 ′ = a i a_{i-1}^\prime=a_{i} ai?1?=ai?,就像上面的让答案更优。但是可能会使得 a i ? 1 ′ < a i ? 2 ′ a_{i-1}^\prime<a_{i-2}^\prime ai?1?<ai?2?,但这并不妨碍我们,因为若我们令 a i ′ = a i ? 1 ′ a_i^\prime=a_{i-1}^\prime ai?=ai?1?,也是多操作了这些步骤,且保证一定是合法的。若 a i ? 1 ′ < a i ? 2 ′ a_{i-1}^\prime<a_{i-2}^\prime ai?1?<ai?2? 成立了,我们变 假装 调整这个序列,通过如下的手段:
1 3 3 3 5 (2) 新加入了 2
因为 2 < 5 ,我们要多操作 5-2=3 次
我们假装变成这样:
1 3 3 55)
在形式上,我们变成这样:
1 3 3 3 (2) 2
但是我们注意到了, 3 > 2,这个序列并不是单递增了
但是我们最后两个 2 可以随便转变为 [2,5] 中的随意数字,都是可以的,我们不妨把这两个点缩成一个点
1 3 3 3 (2)
然后我们再新加进来一个 1
1 3 3 3 2 (1)
注意到,此时序列中最高值为 3 ,我们要多操作 3-1=2 次
同理,序列中最左边的那个 3 和新加进来的 1 ,可以合并成一个点,且取值 [1,3] 都是可以的,我们自然取 1 最优
所以序列新变成了:
1 (1) 3 3 2
注意,这里我们都是假装的序列。如果要求是合法的序列,我们必须取值范围要取得更劣些,就变成这样:
1 [3] 3 3 (3 3) [3]
  • 从代码实现来说,就是用一个优先队列。最大元素为 x x x,现在新加进来一个 y y y
    如果 x ≤ y x\le y xy,我们自然不需要修改,把 y y y 丢进去即可。
    否则,我们需要多 x ? y x-y x?y 次操作,然后把 x x x 丢掉,再把 y y y 丢进去(点合并)
  • CF713C 标准题解是 O ( n 2 ) O(n^2) O(n2) 的离散化 d p dp dp,在评论区有人第一次表述了 O ( n log ? n ) O(n\log n) O(nlogn) 的代码,但是是使用斜率和凸包分析描述的,不是很懂,但代码是相同的,这里提出自己的思考(瞎掰)。

代码

  • 时间复杂度: O ( n log ? n ) O(n\log n) O(nlogn)
#include<bits/stdc++.h>
using namespace std;
void show(){std::cerr << endl;}template<typename T,typename... Args>void show(T x,Args... args){std::cerr << "[ " << x <<  " ] , ";show(args...);}
#define ll long long
const int MAX = 3e2+50;


priority_queue<int>Q;

int main()
{
    int n;scanf("%d",&n);
    ll ans = 0;
    for(int i = 1;i <= n;++i){
        int t;scanf("%d",&t);t -= i;
        Q.push(t);
        if(t < Q.top()){
            ans += Q.top() - t;
            Q.pop();
            Q.push(t);
        }
    }
    printf("%lld",ans);
    return 0;
}

D:Product Oriented Recurrence | CF1182E

题意

思路

  • 之前看有人牛客群里问了 f x = f x ? 1 f x ? 2 f_x=f_{x-1}f_{x-2} fx?=fx?1?fx?2? 的问题咋做,随机就拉到了这题…
    一个很标准的矩阵快速幂的题目,会写的应该都会,稍微变变即可。
  • 第一步,我们记录每个数字 f x = f 1 a × f 2 b × f 3 c × o t h e r s f_x=f_1^{a}\times f_2^b\times f_3^c\times others fx?=f1a?×f2b?×f3c?×others,算出次数 a , b , c a,b,c a,b,c
    容易想到,对于乘积来说,次方是相加的。我们容易写出转移:
    ( 1 1 1 1 0 0 0 1 0 ) ( f n ( a ) f n ( b ) f n ( c ) f n ? 1 ( a ) f n ? 1 ( b ) f n ? 1 ( c ) f n ? 2 ( a ) f n ? 2 ( b ) f n ? 2 ( c ) ) = ( f n + 1 ( a ) f n + 1 ( b ) f n + 1 ( c ) f n ( a ) f n ( b ) f n ( c ) f n ? 1 ( a ) f n ? 1 ( b ) f n ? 1 ( c ) ) \begin{pmatrix} 1&1&1\\ 1&0&0\\ 0&1&0\\ \end{pmatrix} \begin{pmatrix} f_n(a)&f_n(b)&f_n(c)\\ f_{n-1}(a)&f_{n-1}(b)&f_{n-1}(c)\\ f_{n-2}(a)&f_{n-2}(b)&f_{n-2}(c)\\ \end{pmatrix} = \begin{pmatrix} f_{n+1}(a)&f_{n+1}(b)&f_{n+1}(c)\\ f_n(a)&f_n(b)&f_n(c)\\ f_{n-1}(a)&f_{n-1}(b)&f_{n-1}(c)\\ \end{pmatrix} ???110?101?100???????fn?(a)fn?1?(a)fn?2?(a)?fn?(b)fn?1?(b)fn?2?(b)?fn?(c)fn?1?(c)fn?2?(c)????=???fn+1?(a)fn?(a)fn?1?(a)?fn+1?(b)fn?(b)fn?1?(b)?fn+1?(c)fn?(c)fn?1?(c)????
    所以可以得出:
    ( 1 1 1 1 0 0 0 1 0 ) n ? 3 ( 0 0 1 0 1 0 1 0 0 ) = ( f n ( a ) f n ( b ) f n ( c ) f n ? 1 ( a ) f n ? 1 ( b ) f n ? 1 ( c ) f n ? 2 ( a ) f n ? 2 ( b ) f n ? 2 ( c ) ) \begin{pmatrix} 1&1&1\\ 1&0&0\\ 0&1&0\\ \end{pmatrix}^{n-3} \begin{pmatrix} 0&0&1\\ 0&1&0\\ 1&0&0\\ \end{pmatrix} = \begin{pmatrix} f_n(a)&f_n(b)&f_n(c)\\ f_{n-1}(a)&f_{n-1}(b)&f_{n-1}(c)\\ f_{n-2}(a)&f_{n-2}(b)&f_{n-2}(c)\\ \end{pmatrix} ???110?101?100????n?3???001?010?100????=???fn?(a)fn?1?(a)fn?2?(a)?fn?(b)fn?1?(b)fn?2?(b)?fn?(c)fn?1?(c)fn?2?(c)????
  • 第二步,算出那个 f x = c d × o t h e r s f_x=c^d\times others fx?=cd×others 底数为 c c c 的指数是多少,相同的道理,写出转移矩阵
    ( 1 1 1 1 1 ? 2 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 1 ) × ( c i c i ? 1 c i ? 2 2 i 2 ) = ( c i + 1 c i c i ? 1 2 ( i + 1 ) 2 ) \begin{pmatrix} 1&1&1&1&1&-2\\ 1&0&0&0&0&0\\ 0&1&0&0&0&0\\ 0&0&0&0&1&1\\ 0&0&0&0&0&1\\ \end{pmatrix} \times \begin{pmatrix} c_i\\ c_{i-1}\\ c_{i-2}\\ 2i\\ 2 \end{pmatrix} = \begin{pmatrix} c_{i+1}\\ c_{i}\\ c_{i-1}\\ 2(i+1)\\ 2 \end{pmatrix} ???????11000?10100?10000?10000?10010??20011????????×???????ci?ci?1?ci?2?2i2????????=???????ci+1?ci?ci?1?2(i+1)2????????
    所以我们有:
    ( 1 1 1 1 1 ? 2 1 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 1 0 0 0 0 0 1 ) n ? 4 × ( 14 6 2 12 2 ) = ( c n + 2 c n + 1 c n 2 ( n + 2 ) 2 ) \begin{pmatrix} 1&1&1&1&1&-2\\ 1&0&0&0&0&0\\ 0&1&0&0&0&0\\ 0&0&0&0&1&1\\ 0&0&0&0&0&1\\ \end{pmatrix}^{n-4} \times \begin{pmatrix} 14\\ 6\\ 2\\ 12\\ 2 \end{pmatrix} = \begin{pmatrix} c_{n+2}\\ c_{n+1}\\ c_{n}\\ 2(n+2)\\ 2 \end{pmatrix} ???????11000?10100?10000?10000?10010??20011????????n?4×???????1462122????????=???????cn+2?cn+1?cn?2(n+2)2????????
  • 还有一点注意的,由于这里的数字都是指数,根据欧拉降幂,需要取模 φ ( P ) = P ? 1 \varphi(P)=P-1 φ(P)=P?1

代码

  • 时间复杂度: O ( s z 3 × log ? n ) O(sz^3\times \log n) O(sz3×logn)
#include<bits/stdc++.h>
using namespace std;
void show(){std::cerr << endl;}template<typename T,typename... Args>void show(T x,Args... args){std::cerr << "[ " << x <<  " ] , ";show(args...);}
#define ll long long
const int MAX = 3e2+50;
const int MOD = 1e9+6;
const int MOD2 = 1e9+7;
typedef long long Elemtype;
const int SZ = 5;
struct Matrix{
    Elemtype mat[SZ][SZ];
}M1,M2,M3,M0;

Matrix mul(Matrix x,Matrix y,ll sz){
    Matrix ans;
    for(int i=0;i<sz;++i){
        for(int j=0;j<sz;++j){
            ans.mat[i][j]=0;
            for(int k=0;k<sz;++k){
                ans.mat[i][j]+=(x.mat[i][k]*y.mat[k][j])%MOD;
            }
            ans.mat[i][j]%=MOD;
        }
    }
    return ans;
}
ll qpow(ll a, ll n,ll pmod)
{
    ll ans = 1;
    while(n){
        if(n&1){
            ans=ans*a%pmod;
        }
        n>>=1;
        a=a*a%pmod;
    }
    return ans;
}
Matrix Create_Matrix(ll sz){
    Matrix ans;
    for(ll i=0;i<sz;++i)
        for(ll j=0;j<sz;++j)
            if(i==j)ans.mat[i][j]=1;
            else ans.mat[i][j]=0;
    return ans;
}
Matrix M_qpow(Matrix x,ll n,ll sz)
{
    Matrix ans = Create_Matrix(sz);
    while(n){
        if(n&1){
            ans = mul(ans,x,sz);
        }
        n>>=1;
        x = mul(x,x,sz);
    }
    return ans;
}

void show_M(Matrix x,int sz){
    puts("---");
    for(int i = 0;i < sz;++i){
        for(int j = 0;j < sz;++j){
            cout << x.mat[i][j] << " ";
        }
        puts("");
    }
    puts("---");
}

int main()
{
    ll n,a,b,c,d;
    ll ans = 0;
    cin >> n >> a >> b >> c >> d;

    M1.mat[0][0] = M1.mat[0][1] = M1.mat[0][2] = 1;
    M1.mat[1][0] = M1.mat[2][1] = 1;
    M1 = M_qpow(M1,n-3,3);

    M0.mat[0][2] = M0.mat[1][1] = M0.mat[2][0] = 1;

    M1 = mul(M1,M0,3);

    ans = qpow(a,M1.mat[0][0],MOD2) * qpow(b,M1.mat[0][1],MOD2) % MOD2 * qpow(c,M1.mat[0][2],MOD2) % MOD2;

    M2.mat[0][0] = M2.mat[0][1] = M2.mat[0][2] = M2.mat[0][3] = 1;
    M2.mat[0][4] = (-2 + MOD);
    M2.mat[1][0] = M2.mat[2][1] = M2.mat[3][3] = M2.mat[3][4] = M2.mat[4][4] = 1;
    M2 = M_qpow(M2,n-4,5);


    M3.mat[0][0] = 14;
    M3.mat[1][0] = 6;
    M3.mat[2][0] = 2;
    M3.mat[3][0] = 12;
    M3.mat[4][0] = 2;

    M3 = mul(M2,M3,5);


    ans = ans * qpow(d,M3.mat[2][0],MOD2) % MOD2;
    printf("%lld",ans);


    return 0;
}

E:Divisibility Rules | CF180B

题意

思路

  • 前置:
    ? \color{red}{*} ? x n ? 1 = ( x ? 1 ) ( x n ? 1 + x n ? 2 + ? + 1 ) x^n-1=(x-1)(x^{n-1}+x^{n-2}+\cdots+1) xn?1=(x?1)(xn?1+xn?2+?+1)
    ? \color{red}{*} ? x n + 1 = ( x + 1 ) ( x n ? 1 ? x n ? 2 + ? + 1 ) x^n+1=(x+1)(x^{n-1}-x^{n-2}+\cdots+1) xn+1=(x+1)(xn?1?xn?2+?+1) 其中 n n n 是奇数
  • 首先是最简单的 2 ? t y p e 2-type 2?type
    注意到,也就是我们希望满足 d × k = b x d\times k=b^x d×k=bx 对于最小的正整数 x x x 和一个正整数 k k k 成立。
    注意到,此时 d d d 的所有质因子都必须包含于 b b b 的所有质因子。
    代码实现上,若 gcd ? ( d , b ) ≠ 1 \gcd(d,b)\ne 1 gcd(d,b)?=1,则我们每次让 d = d / gcd ? ( d , b ) d=d/\gcd(d,b) d=d/gcd(d,b),没除一次,则 x = x + 1 x=x+1 x=x+1
    此时若 d = 1 d=1 d=1,则就是 2 ? t y p e 2-type 2?type,此时的 x x x 就是最小的 x x x
  • 然后就是 3 , 11 , 6 ? t y p e 3,11,6-type 3,11,6?type
    3 ? t y p e 3-type 3?type,我们需要把 b b b 进制下的 d d d 写出来。
    d = ∑ i = 0 ∞ a i b i d=\sum_{i=0}^\infin a_ib^i d=i=0?ai?bi
    注意到此时我们当然有
    ∑ i = 0 ∞ a i b i ≡ 0 ( m o d d ) \sum_{i=0}^\infin a_ib^i \equiv 0\pmod d i=0?ai?bi0(modd)
    对于 3 ? t y p e 3-type 3?type,我们有
    ∑ i = 0 ∞ a i ≡ 0 ( m o d d ) \sum_{i=0}^\infin a_i \equiv 0\pmod d i=0?ai?0(modd)
    两式子合并,得到:
    ∑ i = 0 ∞ a i ( b i ? 1 ) ≡ 0 ( m o d d ) ∑ i = 0 ∞ a i ( b ? 1 ) ( o t h e r s ) ≡ 0 ( m o d d ) \sum_{i=0}^\infin a_i(b^i-1) \equiv 0\pmod d\\ \sum_{i=0}^\infin a_i(b-1)(others) \equiv 0\pmod d\\ i=0?ai?(bi?1)0(modd)i=0?ai?(b?1)(others)0(modd)
    也就是说 b ? 1 b-1 b?1 d d d 的倍数
  • 然后是 11 ? t y p e 11-type 11?type,同理
    ∑ i = 0 ∞ a i b i ≡ 0 ( m o d d ) ∑ i = 0 ∞ ( ? 1 ) i + 1 a i ≡ 0 ( m o d d ) \sum_{i=0}^\infin a_ib^i \equiv 0\pmod d\\ \sum_{i=0}^\infin (-1)^{i+1}a_i\equiv 0\pmod d i=0?ai?bi0(modd)i=0?(?1)i+1ai?0(modd)
    得到以下式子:
    ∑ i = 0 ∞ a i ( b i + ( ? 1 ) i + 1 ) ≡ 0 ( m o d d ) \sum_{i=0}^\infin a_i(b^i+(-1)^{i+1}) \equiv 0\pmod d\\ i=0?ai?(bi+(?1)i+1)0(modd)
    i i i 是奇数,则会变成 b J + 1 = ( b + 1 ) ( O t h e r s ) b^J+1=(b+1)(Others) bJ+1=(b+1)(Others) 的形式
    i i i 是偶数,则会变成 b 2 x ? 1 = ( b x + 1 ) ( b x ? 1 ) b^{2x}-1=(b^x+1)(b^x-1) b2x?1=(bx+1)(bx?1) x x x 是奇数,那么左边这一项可以分出来一个 ( b + 1 ) ( O t h e r s ) (b+1)(Others) (b+1)(Others);若 x x x 是偶数,那么继续拆 b x ? 1 b^x-1 bx?1,就是一个递归问题了。
  • 所以此时一定有 1 + b 1+b 1+b d d d 的倍数
    注意,以上两种都要求 x = 0 x=0 x=0,也就是 gcd ? ( b , d ) = 1 \gcd(b,d)=1 gcd(b,d)=1
    6 ? t y p e 6-type 6?type,也就是上述有两种同时满足,就是 b + 1 和 b ? 1 b+1和 b-1 b+1b?1 同时是 d d d 的倍数即可。
    ? \color{red}{*} ? 如果符合 3 ? t y p e 3-type 3?type 或者 11 ? t y p e 11-type 11?type,那么一定符合 2 ? t y p e 2-type 2?type
    否则就是 7 ? t y p e 7-type 7?type

代码

  • 时间复杂度: O ( log ? R ) O(\log R) O(logR)
#include<bits/stdc++.h>
using namespace std;
void show(){std::cerr << endl;}template<typename T,typename... Args>void show(T x,Args... args){std::cerr << "[ " << x <<  " ] , ";show(args...);}
#define ll long long
const int MAX = 3e2+50;
const int MOD = 1e9+6;

int lcm(int x,int y){
    return x * y / __gcd(x,y);
}

int main()
{
    int b,d,dd,cnt = 0;
    cin >> b >> d;
    dd = d;
    while(__gcd(dd,b) > 1){
        dd /= __gcd(dd,b);
        cnt++;
    }
    if(dd == 1){
        puts("2-type");
        printf("%d",cnt);
    }else if(!(lcm(b-1,b+1) % dd)){
        if(!cnt && !((b-1) % dd))puts("3-type");
        else if(!cnt && !((b+1) % dd))puts("11-type");
        else puts("6-type");
    }else{
        puts("7-type");
    }
    return 0;
}

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-09-04 17:47:48  更:2021-09-04 17:49:15 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/30 1:18:16-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码