北冰洋以北 发表于 2025-4-1 12:49:53

蓝桥杯自我复习打卡

总复习,打卡2。
二。数论


一,__gcd,lcm

1.最大公约数和最小公倍数标题

关键字:( lcm, _gcd结论)

https://i-blog.csdnimg.cn/direct/32b83d5aaa5b4d1696f5f17ad47d59d4.png
https://i-blog.csdnimg.cn/direct/8a6881b740a84dc6997445455244149b.png
https://i-blog.csdnimg.cn/direct/499d05e038ba414fa1d3dfe9734b2100.png
AC
#include <bits/stdc++.h>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    long long x0, y0;
    cin >> x0 >> y0;

    // 1. 如果 y0 不能被 x0 整除,则答案为 0
    if (y0 % x0 != 0) {
      cout << 0 << "\n";
      return 0;
    }

    // 2. 令 M = y0 / x0
    long long M = y0 / x0;

    // 3. 计数答案
    long long ans = 0;

    // 4. 枚举 M 的因数 a
    for (long long a = 1; a * a <= M; a++) {
      if (M % a == 0) {
            long long b = M / a;
            // 只有 gcd(a, b) == 1 才满足 gcd(x0*a, x0*b) = x0
            if (__gcd(a, b) == 1) {
                // 若 a != b,则 (a,b) 和 (b,a) 两对
                if (a != b) ans += 2;
                // 若 a == b,则只有 1 对
                else ans += 1;
            }
      }
    }

    cout << ans << "\n";
    return 0;
}

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    ll x,y;
    cin >> x >> y;
    ll count = 0;

    // 关键循环:i从x开始,一直到 sqrt(x*y) 为止
    for(ll i = x; i <= sqrt(x*y); i++){
      // 若 i 正好整除 x*y,则 j = (x*y)/i
      // 否则无法组成 (i, j) 使 i*j = x*y
      if( (x*y) % i == 0 ){
            ll j = (x*y) / i;
            // 计算 gcd(i, j)
            ll yueshu = __gcd(i, j);

            // 条件1:gcd(P,Q) = x=>gcd(i,j) = x
            // 条件2:P*Q = x*y (用来保证 lcm(P,Q) = y 也满足)
            //   上面第2条已经用 (x*y)%i == 0 来保证

            if( yueshu == x ){
                // 如果 i == j,则只算1个 (因为 (i,j) == (j,i))
                // 如果 i != j,则算2个 (因为 (i,j) 和 (j,i) 是两种)
                if(i * i == x*y){
                  count += 1;
                }
                else{
                  count += 2;
                }
            }
      }
    }
    cout << count;
    return 0;
}
 https://i-blog.csdnimg.cn/direct/199f5a1c86cb47c59a2e4c4f680217a6.png
https://i-blog.csdnimg.cn/direct/75e25eed215647b7b0d1a175d69043dc.png
https://i-blog.csdnimg.cn/direct/ff0ad4a3247a42bda644298b792d36ac.png
https://i-blog.csdnimg.cn/direct/15339233491c493ba806613d6d571274.png
2.最大公约数 

关键字:(曼哈顿间隔,bfs)

https://i-blog.csdnimg.cn/direct/702240f0ecfe47f0b3f182fae213fa63.png
https://i-blog.csdnimg.cn/direct/eb0621f14c25498fa97b79e63637bc15.png
曼哈顿间隔。 
https://i-blog.csdnimg.cn/direct/9af56c1b0a9f41b19b6f657c1e108d94.png
https://i-blog.csdnimg.cn/direct/5f1e5a3633e247e2afdb593bf9209aa7.png
#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int MAXN=2e3+10;
LL a,d;        //两个数组要开long long类型,数组d要开为 n+m 的最大值
LL GCD(LL a,LL b)
{
    LL c=0;
    while((c=a%b))
    {
      a=b;
      b=c;
    }
    return b;
}
int main()
{
    int n,m,x,y;
    cin>>n>>m;
    for(int i=1;i<=n;i++)
      for(int j=1;j<=m;j++)
            cin>>a;
    cin>>x>>y;
    if(a==1)
    {
      cout<<0;
      return 0;
    }
    for(int i=0;i<=n+m;i++)
      d=a;
    for(int i=1;i<=n;i++)
      for(int j=1;j<=m;j++)
            if(i!=x||j!=y)        //注意需要排除自身
            {
                int dis=abs(x-i)+abs(y-j);
                d=GCD(a,d);
            }
    for(int i=1;i<=n+m;i++)
    {
      d=GCD(d,d);
      if(d==1)
      {
            cout<<i;
            return 0;        //提前结束程序
      }
    }
    cout<<-1;
    return 0;
} bfs
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
struct node{
        ll x,y,val;
};
node mp;
ll vis;
ll dx[]={-1,1,0,0};
ll dy[]={0,0,-1,1};
ll ans=0;
ll x,y;
ll n,m;
void bfs(){
        queue<node> q;
        queue<ll> steps;
       
        q.push({x,y,mp.val});
        steps.push(0);
       
        ll yueshu=mp.val;

        vis=1;
        while(!q.empty()){
                node top=q.front();q.pop();
                ll step=steps.front();steps.pop();
               
                for(ll i=0;i<4;i++){
                        ll nx=top.x+dx;
                        ll ny=top.y+dy;
                        ll value=mp.val;
                  if(nx < 1 || nx > n || ny < 1 || ny > m) continue;
                        if(!vis){
                                yueshu=__gcd(yueshu,value);
                                vis=1;
                                q.push({nx,ny,value});
                                steps.push(step+1);
                                if(yueshu==1){
                                        cout<<step+1<<'\n';
                                        return;
                                }
                        }
                }
        }
        cout<<-1;
}
int main(){
        ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
        cin>>n>>m;
        for(ll i=1;i<=n;i++){
                for(ll j=1;j<=m;j++){
                        cin>>mp.val;
                }
        }
        cin>>x>>y;
        if(mp.val==1){
                cout<<0;
                return 0;
        }
        bfs();
        return 0;
} 3.斐波那契公约数

关键字:(鸽巢原理,黄金分割比,矩阵快速幂)

https://i-blog.csdnimg.cn/direct/050099af07df4322bc2bc7cea205110f.png
。。。前面那么多斐波那契数,纸上摆列一下,相邻两对最大公约数 基本都是1,直接暴力输出1,一个测试点也没过。。由于标题问的是恣意两个斐波那契数的最大公因数。
打个表看看规律。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=1e8;
ll n,m;
int main(){
        ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
        cin>>n>>m;
        ll a;
        a=0,a=1;
        for(ll i=2;i<50;i++){
                a=a+a;
        }
        for(ll i=1;i<=49;i++){
                for(ll j=1;j<=49;j++){
                        if(i!=j){
                                cout<<a<<""<<a<<"";
                                cout<<__gcd(a,a)%N<<'\n';
                        }
                }
        }
        return 0;
} https://i-blog.csdnimg.cn/direct/c26ce73f43a04813a3fda65ea2b60fc2.png
https://i-blog.csdnimg.cn/direct/f0df58ff8acc475eaf20ad815517501e.png
大部分是1,大概来那个数中较小的那个,很少别的数字。


大佬解法:
https://i-blog.csdnimg.cn/direct/2cf02598f965470392635a1235be086b.png
https://i-blog.csdnimg.cn/direct/fb0c44e6d3844b53b5ed2162dff54a5b.png



https://i-blog.csdnimg.cn/direct/6c12e74d4ad244948fa9e88db17e367b.png
https://i-blog.csdnimg.cn/direct/d1a93f4ce0c543e7b5ab93de477a0ae2.png
https://i-blog.csdnimg.cn/direct/d9d84bb3e3ad49db91868c41c369d848.png
https://i-blog.csdnimg.cn/direct/29f40c23baba4cb399af44a7c89cb8d2.png
https://i-blog.csdnimg.cn/direct/839e1af1be3e41518e1334a3050dabd0.png
https://i-blog.csdnimg.cn/direct/32f6d8224d7f48ec86ec69292891d110.png
  代码思路捋一下,其实就是,我们想求__gcd(f,f),根据斐波那契数列性子可以知道,__gcd(f,f)=f(__gcd(n,m)),以是标题转化为了求  f(__gcd(n,m)),看标题数据范围,1≤n,m≤109。假如单纯的递归求f(__gcd(n,m)),标题也很复杂,我们就想到了使用这个递推关系,构建一个关系矩阵,递推发现   f(__gcd(n,m))   =  (关系矩阵)^n    *   矩阵({0,1}),标题就更进一步的简化了,我们只用求关系矩阵的n次方即可。标题迎刃而解。
  注意:直接暴力算关系矩阵的n次方还是会超时,必须得用矩阵快速幂。

#include <iostream>
#include <numeric>// for gcd
using namespace std;
typedef long long ll;

const ll MOD = 100000000;// 10^8

// 定义 2x2 矩阵结构体
struct Matrix {
        ll m;
};

// 矩阵乘法(2x2 矩阵),结果取模 MOD
Matrix multiply(const Matrix &A, const Matrix &B) {
        Matrix C;
        C.m = (A.m * B.m + A.m * B.m) % MOD;
        C.m = (A.m * B.m + A.m * B.m) % MOD;
        C.m = (A.m * B.m + A.m * B.m) % MOD;
        C.m = (A.m * B.m + A.m * B.m) % MOD;
        return C;
}

// 矩阵快速幂,计算 base^exp
Matrix matrixPower(Matrix base, ll exp) {
        // 初始化单位矩阵
        Matrix result = {{{1, 0}, {0, 1}}};
        while(exp > 0) {
                if(exp & 1) {
                        result = multiply(result, base);
                }
                base = multiply(base, base);
                exp >>= 1;// exp 除以 2
        }
        return result;
}

int main(){
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
       
        ll n, m;
        cin >> n >> m;
       
        // 利用性质: gcd(f(n), f(m)) = f(gcd(n, m))
        ll d = std::gcd(n, m);
       
        // 斐波那契转换矩阵 T = [,]
        Matrix T = {{{0, 1}, {1, 1}}};
       
        // 计算 T^d
        Matrix T_d = matrixPower(T, d);
       
        // 根据性质:
        // T^d = [ , ]
        // 所以 f(d) 就是 T^d
        cout << T_d.m % MOD << "\n";
        return 0;
}
https://i-blog.csdnimg.cn/direct/f18cb7b603854780940ae7a9c23ecace.png https://i-blog.csdnimg.cn/direct/d2bb936bea59414b80cb4874df7f069d.png
 这鸽巢原理,直接省去好大的麻烦,我就说数学学好很有用吧!nnnnnnnnnnb!
https://i-blog.csdnimg.cn/direct/1e61377c33394d91b023f93757696ef8.png
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=1e8;
ll n,m;
ll f;
int main(){
        ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
        cin>>n>>m;
        n=__gcd(n,m);
        f=1;
        f=1;
        if(n>150000000)n%=150000000;
       
        for(ll i=3;i<=n;i++){
                f=(f[(i-1)%3]%N)+(f[(i-2)%3]%N);
        }
        cout<<f%N;
        return 0;
} https://i-blog.csdnimg.cn/direct/8ff5efffe53c44059bc15601eb48d126.pnghttps://i-blog.csdnimg.cn/direct/5c64524644ef48b6a75e29e9e9154150.png 
 https://i-blog.csdnimg.cn/direct/9be388cba3404935b000d262a418f9ab.png
 https://i-blog.csdnimg.cn/direct/2081119d8b1d446ca696bddb34648999.png
4.因子和 

关键字:(质因数分解,快速幂,费马小定理,分治思想)

https://i-blog.csdnimg.cn/direct/03737dfb15c5433bbada5af6af915806.png
这个标题不要试图先求a^b,由于当a,b,都趋近5*1e7时,得到的结果远远超过long long ,即使用字符串处理惩罚也会丢失精度,超时。以是可以先从a分解入手,化简发现一个式子,再使用费马小定理结合快速幂即可解题。
https://i-blog.csdnimg.cn/direct/e31caaf29c9e45bfa076ddd177678ebd.png
https://i-blog.csdnimg.cn/direct/71b1b86f28e94840ae4dfd0528e5ab06.png
https://i-blog.csdnimg.cn/direct/4541f431351d4fa69d216f1562f26388.png
https://i-blog.csdnimg.cn/direct/62e92fad6492404ea135c32915ebcdd7.png
https://i-blog.csdnimg.cn/direct/f036cf593b1b461f8228f87b75f6ce07.png
https://i-blog.csdnimg.cn/direct/194863491acb4b93b26f4d53de01d495.png
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a,b;
ll qsm(ll a,ll b){
        ll res=1;
        a%=9901;
        while(b){
                if(b&1)res=(res*a)%9901;
                a=a%9901*a%9901;
                b>>=1;
        }
        return res%9901;
}
ll sum(ll base,ll zhishu){
        if(base%9901==1){
               
                return (zhishu*b+1)%9901;
               
        }else{
                ll cur1=(qsm(base,zhishu*b+1)-1)%9901;
                if(cur1<0)cur1+=9901;//要加上这个判断不然会有一个测试点过不了
                ll cur2=qsm((base-1)%9901,9901-2);
                if(cur2<0)cur2+=9901;
                return cur1 %9901 *cur2 %9901;
        }
}                                 
int main(){
        ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
        cin>>a>>b;
        ll res=1;
        ll t=a;
        for(ll i=2;i*i<=t;i++){
                ll cnt=0;
                while(t%i==0){
                        cnt++;
                        t/=i;
                }
                res=(res %9901 *sum(i,cnt))%9901;
                //别写res*=(sum(i,cnt))%9901不然容易爆,会有一个测试点不补了
        }
        if(t!=1){
                res=(res*sum(t,1))%9901;
        }
        cout<<res%9901;
        return 0;
}
/*
a = p1^x1 * p2^x2 * p3^x3 * ....pk^xk;
a^b = (p1^x1 * p2^x2 * p3^x3 * ....pk^xk)^b;
a^b = (p1^(x1*b) * (p2^(x2*b)) * .....(pk^(xk*b));
a^b = (p1^1 + p1^2 +.....p1^(x1*b)) * (p2^1 + p2^2 + .....p2^(xk*b)).....

if( (p1^(x1*b) %9901 ==1){//等于0时没意义
      a^b = (1+1+1....) * (1+1....) *....
      a^b = (x1*b+1)*1*(x2*b+1)....
}
else 老老实实算
a^b = ( (p1^(x1*b) - 1) / (p1 - 1) ) % 9901 * ( (p2^(x2*b) - 1) / (p2 - 1) ) % 9901.....
a^b = ( (p1^(x1*b) - 1) * (p1-1)^(-1) ) %9901 *.....

*/ #include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const ll mod = 9901;
ll a, b;

// 快速幂(计算 a^b mod mod)
ll qsm(ll a, ll b) {
    ll res = 1;
    a %= mod;
    while(b) {
      if(b & 1) res = (res * a) % mod;
      a = (a * a) % mod;
      b >>= 1;
    }
    return res;
}

// 计算几何级数和:1 + p^b + p^(2b) + ... + p^(e*b)
// e 为 a 中 p 的指数,即 a^b 中 p 的指数为 e*b
ll sum(ll p, ll e) {
    ll exp_total = e * b; // a^b 中 p 的最高指数
    // 如果 p ≡ 1 (mod mod),则 p^j ≡ 1,和就是 (exp_total+1)
    if(p % mod == 1) {
      return (exp_total + 1) % mod;
    } else {
      // 根据等比数列求和公式:
      // S = (p^(exp_total+1) - 1) / (p - 1) mod mod
      ll numerator = (qsm(p, exp_total + 1) - 1) % mod;
      if(numerator < 0) numerator += mod;
      ll denominator = (p - 1) % mod;
      if(denominator < 0) denominator += mod;
      // 利用费马小定理求模逆元 (mod 为质数)
      ll invdenom = qsm(denominator, mod - 2);
      return (numerator * invdenom) % mod;
    }
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
   
    cin >> a >> b;
    ll res = 1;
    ll tmp = a;
   
    // 质因数分解
    for(ll i = 2; i * i <= tmp; i++){
      if(tmp % i == 0){
            ll cnt = 0;
            while(tmp % i == 0){
                cnt++;
                tmp /= i;
            }
            res = (res * sum(i, cnt)) % mod;
      }
    }
    // 如果 tmp 不为 1,则剩余 tmp 为质因子
    if(tmp != 1) {
      res = (res * sum(tmp, 1)) % mod;
    }
   
    cout << res % mod << "\n";
    return 0;
}

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll a,b,ans=1,mod=9901;
ll ksm(ll x,ll y){//快速幂
        ll res=1;
        while(y){
                if(y%2==1)res=res*x%mod;
                x=x*x%mod;
                y/=2;
        }
        return res;
}
ll sum(ll x,ll y){//等比数列和
        if(x==0)return 1;
        if(x%2==1)return sum(x/2,y)*(1+ksm(y,x/2+1))%mod;
    //偶数项,分两部分算(后半就是前半乘y^(x/2+1))
        return (sum(x/2-1,y)*(1+ksm(y,x/2+1))+ksm(y,x/2))%mod;
    //奇数项,加上中间一项
//因算了y^0,所以x%2==1是偶数项
}
int main (){
        cin>>a>>b;
        for(int i=2;i<=sqrt(a);i++){//质因数分解
                int c=0;
                while(a%i==0){
                        a/=i;
                        c++;
                }
                ans=ans*sum(c*b,i)%mod;
        }
        if(a!=1)
        ans=ans*sum(b,a)%mod;
        cout<<ans;
} 5. 最大公约数

关键字:(稀疏表,二分查找,线段树)

https://i-blog.csdnimg.cn/direct/8040ff79e7344180a07ef0b4fff8650e.png
AC(稀疏表) 
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

// 求两个数的最大公约数
ll gcd(ll a, ll b) {
    return b == 0 ? a : gcd(b, a % b);
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
   
    int n;
    cin >> n;
    vector<ll> a(n);
    for (int i = 0; i < n; i++){
      cin >> a;
    }
   
    // 如果数组中已有 1,直接把其他数字“变为 1”
    int ones = 0;
    for (int i = 0; i < n; i++){
      if(a == 1) ones++;
    }
    if(ones > 0){
      cout << (n - ones) << "\n";
      return 0;
    }
   
    // 检查整个数组的 gcd,如果大于 1,则永远无法生成 1
    ll overall = a;
    for (int i = 1; i < n; i++){
      overall = gcd(overall, a);
    }
    if(overall > 1){
      cout << -1 << "\n";
      return 0;
    }
   
    // 数组中没有 1 且整体 gcd 为 1,则一定存在某个子区间的 gcd 为 1
    // 利用稀疏表快速查询任一区间的 gcd
    int logn = floor(log2(n)) + 1;
    vector<vector<ll>> st(n, vector<ll>(logn, 0));
    for (int i = 0; i < n; i++){
      st = a;
    }
    for (int j = 1; j < logn; j++){
      for (int i = 0; i + (1 << j) - 1 < n; i++){
            st = gcd(st, st);
      }
    }
   
    // 预处理 logs 数组,方便查询
    vector<int> logs(n+1);
    logs = 0;
    for (int i = 2; i <= n; i++){
      logs = logs + 1;
    }
   
    // lambda 函数,快速查询区间 内的 gcd
    auto query = [&](int L, int R) -> ll {
      int j = logs;
      return gcd(st, st);
    };
   
    // 枚举每个起点,利用二分查找找出最短区间长度使得 gcd=1
    int best = INT_MAX;
    for (int i = 0; i < n; i++){
      int lo = i, hi = n - 1, pos = -1;
      while(lo <= hi){
            int mid = (lo + hi) / 2;
            if(query(i, mid) == 1){
                pos = mid;
                hi = mid - 1;
            } else {
                lo = mid + 1;
            }
      }
      if(pos != -1){
            best = min(best, pos - i);
      }
    }
   
    // 先需要 (best) 次操作在某个位置“制造出” 1(实际上是 best 次操作把那个区间变为 1,注意原代码中是 (L-1) 次操作,
    // 这里由于我们用的是区间长度差值 pos-i,所以总操作数为 best + (n - 1))
    cout << best + (n - 1) << "\n";
   
    return 0;
}

非AC 
https://i-blog.csdnimg.cn/direct/fabf39e0adb4431698d54bdfdf198fd8.png

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
   
    ll n;
    cin >> n;
   
    // 单独讨论 n == 1 的情况
    if(n == 1){
      ll x;
      cin >> x;
      cout << (x == 1 ? 0 : -1) << "\n";
      return 0;
    }
   
    vector<ll> a(n);
    bool hasOne = false;
    for(ll i = 0; i < n; i++){
      cin >> a;
      if(a == 1) hasOne = true;
    }
   
    // 如果数组中已有1,则直接将所有非1转变为1,每个非1只需一次操作
    if(hasOne){
      ll cnt = 0;
      for(ll i = 0; i < n; i++){
            if(a != 1) cnt++;
      }
      cout << cnt << "\n";
      return 0;
    }
   
    // 如果所有元素都相同,则无法变成全1(因为此时不可能通过 gcd 操作出现1)
    set<ll> s(a.begin(), a.end());
    if(s.size() == 1){
      cout << -1 << "\n";
      return 0;
    }
   
    /*
      以下思路:
      - 数组全为偶数时无法通过相邻操作得到1(因为偶数 gcd 偶数仍为偶数)。
      - 只要有奇数,则有可能通过操作把某个数变成1。
      - 如果有两个以上奇数,根据你的思路直接输出 n(认为最少操作次数为 n)。
      - 如果只有1个奇数,则尝试与相邻元素通过反复 gcd 得到1,
      然后用得到的1扩散到整个数组(每个非1需要一次操作)。
    */
   
    ll oddCount = 0;
    for(ll i = 0; i < n; i++){
      if(a & 1) oddCount++;
    }
   
    // 若全为偶数,则无法得到1
    if(oddCount == 0){
      cout << -1 << "\n";
      return 0;
    }
   
    // 当奇数个数大于等于2时,根据你的注释直接输出 n
    if(oddCount >= 2){
      cout << n << "\n";
      return 0;
    }
   
    // 下面处理奇数个数恰好为1的情况
    ll idx = -1;
    for(ll i = 0; i < n; i++){
      if(a & 1){
            idx = i;
            break;
      }
    }
   
    // 使用 _gcd 替换 std::gcd(在 <algorithm> 中提供)
    if(idx == 0){
      if(__gcd(a, a) == 1){
            cout << n << "\n";
      } else {
            ll cnt = 0;
            while(__gcd(a, a) != 1){
                cnt++;
                a = __gcd(a, a);
            }
            cout << cnt + (n - 1) << "\n";
      }
    }
    else if(idx == n - 1){
      if(__gcd(a, a) == 1){
            cout << n << "\n";
      } else {
            ll cnt = 0;
            while(__gcd(a, a) != 1){
                cnt++;
                a = __gcd(a, a);
            }
            cout << cnt + (n - 1) << "\n";
      }
    }
    else{
      // idx 在中间位置,取其相邻两个数中的较小值作为参考
      ll neighbor = min(a, a);
      if(__gcd(a, neighbor) == 1){
            cout << n << "\n";
      } else {
            ll cnt = 0;
            while(__gcd(a, neighbor) != 1){
                cnt++;
                a = __gcd(a, neighbor);
            }
            cout << cnt + (n - 1) << "\n";
      }
    }
   
    return 0;
}
 https://i-blog.csdnimg.cn/direct/af8abf7497bb4b05b40676c3606e1ffe.png
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
        ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
        ll n;cin>>n;
        ll a;
        ll ones=0;
        for(ll i=0;i<n;i++){
                cin>>a;
                if(a==1)ones++;
        }
        if(ones>0){
                cout<<n-ones<<'\n';
                return 0;
        }
                /*
                  数字全都一样变不了。
                  全为偶数变不了。
                  检查整个数组的 gcd,如果大于 1,则永远无法生成 1
                  只要有1个1,必然可以变,先找一对类似4 6的组合
                  变成2 3然后就可以获得一个1了,有一个1,剩下的1个数需要1次操作即可
                  有两个以上的奇数的,先选择奇奇组合,奇偶组合
                  找最小的奇数(不,对管他多大,反正都可以直接变成1,)和其相邻的最小的偶数组合在一起变小,
                  谁的相邻偶数小,就选谁
               */
        ll gongyueshu=a;
        for(ll i=1;i<n;i++) gongyueshu=__gcd(gongyueshu,a);
        if(gongyueshu>1){
                cout<<-1;
                return 0;
        }
        ll ans=1e9;
        for(ll i=0;i<n;i++){
                ll x=a,cnt=0;
                for(ll j=i+1;j<n;j++){
                  cnt++;
                        x=__gcd(x,a);
                        if(x==1){
                                ans=min(ans,cnt);
                                break;
                        }
                }
        }
        if(ans==1e9)cout<<-1;
        else cout<<n+ans-1;
        return 0;
} AC 
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

// 求最大公约数
ll _gcd(ll a, ll b) {
    return b == 0 ? a : _gcd(b, a % b);
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
   
    int n;
    cin >> n;
    vector<ll> a(n);
    for(int i = 0; i < n; i++){
      cin >> a;
    }
   
    // 如果数组中已有 1,则直接用“扩散”操作:
    int ones = 0;
    for (int i = 0; i < n; i++){
      if(a == 1)
            ones++;
    }
    if(ones > 0){
      cout << (n - ones) << "\n";
      return 0;
    }
   
    // 检查整个数组的 gcd 是否为1
    ll overall = a;
    for (int i = 1; i < n; i++){
      overall = _gcd(overall, a);
    }
    if(overall > 1){
      cout << -1 << "\n";
      return 0;
    }
   
    // dp 用来维护所有以当前位置结尾的区间的 gcd 及其最短区间长度
    // 每个元素为 {g, len},表示:某个子区间的 gcd 为 g,长度为 len
    vector<pair<ll,int>> dp;
    int best = INT_MAX; // 最短区间长度使得 gcd==1
    for (int i = 0; i < n; i++){
      vector<pair<ll,int>> ndp;
      // 新区间:仅包含 a
      ndp.push_back({a, 1});
      
      // 将前面 dp 中的所有区间与 a 合并
      for (auto &p : dp) {
            ll newg = _gcd(p.first, a);
            int newlen = p.second + 1;
            // 如果 ndp 最后一个元素与 newg 相同,则保留较短的长度
            if(!ndp.empty() && ndp.back().first == newg) {
                ndp.back().second = min(ndp.back().second, newlen);
            } else {
                ndp.push_back({newg, newlen});
            }
      }
      
      // 更新答案:若存在 gcd==1 的子区间,记录其长度
      for(auto &p : ndp) {
            if(p.first == 1) {
                best = min(best, p.second);
            }
      }
      dp = ndp;
    }
   
    // 根据题意:先在某个位置用 (L - 1) 次操作制造出 1,
    // 然后用 (n - 1) 次操作将1扩散到整个数组。
    // 注意 L 为最短子区间长度(best)
    int ans = (best - 1) + (n - 1);
    cout << ans << "\n";
   
    return 0;
}

二,快速幂,费马小定理

1.矩阵快速幂(模版题)

关键字:(矩阵快速幂)

https://i-blog.csdnimg.cn/direct/16b00c6d012d4b89aaa9f259de961d27.png
https://i-blog.csdnimg.cn/direct/11d0e6101e1544de8175050f395bfaf0.png
https://i-blog.csdnimg.cn/direct/85fd3f234f23427290d74dfddd4a725a.png
https://i-blog.csdnimg.cn/direct/31d9eb00706841c6ba52f1ac67a92a2f.png
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=1e9+7;
typedef vector<vector<ll>> vec;
// 假设矩阵是 n x n(1-index化),因此实际数组大小是 n+1 x n+1

vec juzhen_mul(const vec &A, const vec &B) {
        /*
        ll n = A.size();
        vec C(n, vector<ll>(n, 0));
          这么写会runtime error
       */
        ll n = A.size()-1;
        vec C(n+1, vector<ll>(n+1, 0));
        for (int i = 1; i <= n; i++){
                for (int k = 1; k <= n; k++){
                        // 提前计算 A,可以减少重复访问
                        ll temp = A;
                        for (int j = 1; j <= n; j++){
                                C = (C + temp * B) % N;
                        }
                }
        }
        return C;
}

vec qsm(vec x,ll k,ll n){
        vec res(n+1,vector<ll>(n+1,0));
        for(ll i=1;i<=n;i++){
                res=1;
        }
       
        while(k){
                if(k&1)res=juzhen_mul(res,x);
                x=juzhen_mul(x,x);
                k>>=1;
        }
        return res;
}
int main(){
        ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
        ll n,k;cin>>n>>k;
        vec mp(n+1,vector<ll>(n+1,0));
        for(ll i=1;i<=n;i++){
                for(ll j=1;j<=n;j++){
                        cin>>mp;
                        mp=mp%N;
                        if(mp<0)mp+=N;
                }
        }
       
       
        //for(ll i=1;i<=n;i++)for(ll j=1;j<=n;j++)cout<<mp<<'\n';
        vec ans=qsm(mp,k,n);
       
        for(ll i=1;i<=n;i++){
                for(ll j=1;j<=n;j++){
                        cout<<ans%N<<" ";
                }
                cout<<'\n';
        }

        return 0;
}
2.高精小数幂

关键字:(高精度,快速幂)

https://i-blog.csdnimg.cn/direct/2a40189ead9648499e9ab0248d563bcc.png
抛开小数不谈,本题求a^n,由于数字较大,要用到高精算法,n的值不大,可以不消快速幂。
本题a可能是小数,可以如许解决,先记载a的小数位数pt,并将a乘以10^pt,转化为整数a′,求出a′^n,设为s′,答案即是s′/(10×pt×n),即输出时将s′的末尾pt×n位作为小数输出即可。
例:求1.25^2,先求125^2,即是15625,由于1.25有两位小数,1.25^2就有4位小数,所有用果即是1.5625。

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1300;                //100000^250有1250位
int pt;
struct Bign{
        int s, len;
        Bign(int num = 0){
                memset(s, 0, sizeof(s));
                len = 1;
                s = num;
        }
        Bign operator * (int b)const{
                Bign c;
                c.len = len + 10;
                for (int i = 1; i <= c.len; i++){
                        c.s += s * b;
                        c.s = c.s / 10;
                        c.s %= 10;
                }
                c.clean();
                return c;
        }
        void clean(){
                while (len > 1 && !s) len--;
        }
};
ostream& operator << (ostream &out, const Bign &x){
        int i;
        for (i = x.len; i > 0 && i > pt; i--)                //输出整数部分
                out << x.s;
        if (i){                                                        //若i不为0,表示还有小数部分
                out << ".";                                        //先输出"."
                for (i = pt; i > 0; i--)        //再输出小数部分
                        out << x.s;
        }
        return out;       
}
int main(){
        double a;
        int n;
        while (cin >> a >> n){
                //求a的小数位数
                pt = 0;                                                                //pt记录a的小数位数
                while (fabs(a - round(a)) > 1e-6){        //若a不等于a的整数部分,表示a不是整数
                        pt++;                                                        //小数位数加一位
                        a *= 10;
                }
                pt *= n;                                                        //a^n的小数位数等于a的小数位数 ×n
                //求s = a ^ n
                Bign s = 1;
                for (int i = 1; i <= n; i++)
                        s = s * (int)round(a);
                cout << s << endl;
        }
        return 0;
} 这题不发起用快速幂,否则不太轻易调试的,而且比力冗长,直接模拟就好了。
 https://i-blog.csdnimg.cn/direct/f7007799b55c4c05869918fc3e77f5bb.png
https://i-blog.csdnimg.cn/direct/ef7974a0b157496686361f326ccab5d4.png
这也是c下标是k+j缘故原由。 
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

// 全局定义,和原C代码一致,只是将 int 改成 long long
// 存放每位数字的数组 a[], b[], c[] 以及输入字符串 s[]
ll a, b, c;
char s;

int main() {
        ios::sync_with_stdio(false);cin.tie(nullptr);
       
        string s;ll n;
        while (cin>>s>>n) {
               
                // 1) 初始化
                memset(a, 0, sizeof(a));
                ll t = 0;    // 记录整数部分位数
                ll flag = 0; // 判断是否有小数点
                ll len = s.length();
               
                // 2) 找到小数点位置
                ll i, j, k;
               
                size_t pos = s.find('.');
                if (pos != string::npos) {
                        t = pos;      // 小数点前的数字个数
                        len--;      // 去掉小数点后长度减1
                        // 将小数点后面的字符向前移动覆盖小数点
                        for (j = pos; j < s.length(); j++) {
                                s = s;
                        }
                } else {
                        t = len;
                }
               
                // 4) 计算最终要保留的小数位数 point = (原小数位数)×n
                //    (原小数位数) = (len - t)
                ll point = (len - t) * n;
               
                // 5) 把去掉 '.' 后的数字逆序存到 a[],a是最低位
                for (i = 0; i < len; i++) {
                        a = (s - '0'); // 字符转数字
                }
               
                // 6) 用 b[] 表示累乘结果,初值为 1
                memset(b, 0, sizeof(b));
                b = 1;
                ll len1 = 1; // b[]当前的有效位数
               
                // 7) 计算 a^n:重复乘法
                for (i = 1; i <= n; i++) {
                        memset(c, 0, sizeof(c));
                        // 竖式乘法:b×a => c
                        for (j = 0; j < len; j++) {
                                for (k = 0; k < len1; k++) {
                                        c += a * b;
                                }
                        }
                        // 处理进位
                        for (k = 0; k < len + len1; k++) {
                                c += c / 10;
                                c %= 10;
                        }
                        // 拷贝结果回 b[]
                        memcpy(b, c, sizeof(c));
                        // 更新 b 的长度
                        len1 += len;
                }
               
                // 8) 去掉最高位多余 0
                while (b == 0 && len1 > 0) {
                        len1--;
                }
               
                // 9) 输出:先输出整数部分 b
                //    (当 point>len1 时,可能只输出几个数字或为 0)
                for (i = len1; i >= point; i--) {
                        cout << b;
                }
               
                // 10) 判断小数部分是否全为0,如果不是,就输出
                for (i = 0; i < point; i++) {
                        if (b != 0) {
                                break;
                        }
                }
                // 如果小数部分有非零,则输出
                if (i < point) {
                        cout << ".";
                        for (ll j = point - 1; j >= i; j--) {
                                cout << b;
                        }
                }
               
                cout << "\n";
        }
        return 0;
} #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a, b, c;
char s;
int main() {
        ios::sync_with_stdio(false);cin.tie(nullptr);
        string s;ll n;
        while (cin>>s>>n){
                ll len=s.length();
                memset(a,0,sizeof(a));
                memset(b,0,sizeof(b));
               
                size_t idx=s.find('.');
                ll t=0;
                if(idx!=string::npos){
                        t=idx;
                        len--;
                        for(ll i=idx;i<s.length();i++)s=s;
                }else t=len;
               
                ll point=(len-t)*n;
                for(ll i=0;i<len;i++)a=s-'0';
               
                b=1;
                ll len1=1;
                for(ll i=1;i<=n;i++){
                        memset(c,0,sizeof(c));
                        for(ll j=0;j<len;j++){
                                for(ll k=0;k<len1;k++){
                                        c+=a*b;
                                }
                        }
                       
                        for(ll j=0;j<len1+len;j++){
                                c+=c/10;
                                c%=10;
                        }
                       
                        memcpy(b,c,sizeof(c));
                        len1+=len;
                }
                while(b==0&&len1>0)len1--;
               
                ll i=len1;
                for(i=len1;i>=point;i--)cout<<b;
                //if(idx!=string::npos)cout<<'.';
       
                for(i=0;i<point;i++){//注意下标的使用,这里用i,还能保证直接对后面的i<point进行判断
                        if(b!=0){
                                break;
                        }
                }
                if(i<point){
                        cout<<'.';
                        for(ll j=point-1;j>=i;j--)cout<<b;
                }
                cout<<'\n';
        }
        return 0;
}
3.小猫

关键字:(快速幂,卡特兰数)

https://i-blog.csdnimg.cn/direct/cd7876244ed142edbe8cb8a8d38f448a.png
 https://i-blog.csdnimg.cn/direct/e8fe794def9f48679654757f781d8155.png
https://i-blog.csdnimg.cn/direct/c7f9e5bfa65140448d53bec6cddf680f.png
https://i-blog.csdnimg.cn/direct/b4533e3da85647bd920a55ff8b4c4b33.png
https://i-blog.csdnimg.cn/direct/9d1e17a609e744b5b0c087927b3203b1.png
https://i-blog.csdnimg.cn/direct/08d409df95cd4fbe9485853e0a234fb9.png
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=1e9+7;
ll qsc(ll a,ll b){
        a%=N;b%=N;
        ll c=(a%N *b%N)/N;
        ll ans=a*b-c*N;
        if(ans<0)ans+=N;
        else ans-=N;
        return ans;
}
ll qsm(ll a,ll b){
        ll res=1;
        a%=N;
        while(b){
                if(b&1)res=(res%N*a%N)%N;
                a=(a%N*a%N)%N;
                b>>=1;
        }
        return res%N;
}
int main(){
        ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
        ll n;cin>>n;
        ll ans1=1,ans2=1,ans3=1;
        for(ll i=1;i<=2*n;i++){
                if(i<=n)ans1=qsc(ans1,i)%N;
                if(i<=n+1)ans2=qsc(ans2,i)%N;
                ans3=qsc(ans3,i)%N;
        }
        ll ans4=qsm(qsc(ans1,ans2),N-2);
        ll final=qsc(ans3,ans4);
        cout<<final%N;
        return 0;
}
/*
也就是求(2*n)! / (n)! *(n+1)!
*/
4.模意义下的乘法逆元

关键字:(快速幂,费马小定理,拓展欧几里得算法)

https://i-blog.csdnimg.cn/direct/96d95c173c2545519340390ac81aeefa.png

https://i-blog.csdnimg.cn/direct/2373c617656b44edb44600d69d2120c2.png 非AC
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll qsm(ll a,ll b,ll p){
        ll res=1;
        while(b){
                if(b&1)res=res%p*a%p;
                a=a%p*a%p;
                b>>=1;
        }
        return res%p;
}
int main(){
        ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
        ll n,p;cin>>n>>p;
        for(ll i=1;i<=n;i++){
                cout<<qsm(i,p-2,p)%p<<'\n';
        }
        return 0;
}  AC
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll qsm(ll a,ll b,ll p){
        ll res=1;
        while(b){
                if(b&1)res=res%p*a%p;
                a=a%p*a%p;
                b>>=1;
        }
        return res%p;
}
int main(){
        ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
        ll n,p;cin>>n>>p;
        ll c;//存储阶乘
        c=1;
        for(ll i=1;i<=n;i++){
                c=c*i%p;
        }
        ll ans;//存答案
        ll pow=(qsm(c,p-2,p))%p;//要有这步,不然后面重复计算会超时
        ll k=0;
        for(ll i=n;i>=1;i--){
                k=(pow*i)%p;//变成了(n-1)!的逆元了。
                ans=pow %p *c%p;
                pow=k;
        }
        for(ll i=1;i<=n;i++)cout<<ans%p<<'\n';
        return 0;
}  https://i-blog.csdnimg.cn/direct/4c9b2179e8444ef09ed96622bc318fac.png
AC
#include <iostream>
#include <vector>
using namespace std;

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n, p;
    cin >> n >> p;
   
    // 存储 1~n 的逆元,注意题目要求 1≤n<p
    vector<int> inv(n + 1, 0);
    inv = 1;
    for (int i = 2; i <= n; i++){
      // 根据公式:inv = (p - (p / i)) * inv mod p
      inv = (int)((long long)(p - p / i) * inv % p);
    }
   
    for (int i = 1; i <= n; i++){
      cout << inv << "\n";
    }
   
    return 0;
}
AC 
#include <stdio.h>

char pc_buf, *pc_p= pc_buf;
#define pc(c) *pc_p++= c;

void write(int x) {
    static int sta;
    register int top= 0;
    do { sta[++top]= x % 10, x/= 10; } while(x);
    while(top) pc(sta ^ 48);
}

int inv(int a,int m){
    register int x=1,y=0,q=0,mod=m;
    while(1){
      if(m) y-=q*x,q=a/m,a-=q*m;
      else return a==1? (x<0? (x+mod)%mod : x) : 0;
      if(a) x-=q*y,q=m/a,m-=q*a;
      else return m==1? (y<0? (y+mod)%mod : y) : 0;
    }
}
int main(){
    int n,p;
    scanf("%d %d",&n,&p);
    for(register int i=1;i<=n;i++)
      write(inv(i,p)),pc('\n');
    fwrite(pc_buf,1,pc_p-pc_buf,stdout);
    return 0;
}     https://i-blog.csdnimg.cn/direct/789dea63411441d08f76df473ef30bc5.png

5.因子和(同上4.因子和)

三,线性筛,埃拉筛,质因数分解

1.线性筛素数(模版题)

关键字:(线性筛,埃拉筛)

https://i-blog.csdnimg.cn/direct/c7f2b2d9a1af4ae79825d44e4328a420.png
埃拉托色尼筛法
#include <bits/stdc++.h>
using namespace std;

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n, q;
    cin >> n >> q;
    // 使用 bitset 存储 的标记(n=1e8时需要 100,000,001 位,约 12.5 MB 内存)
    bitset<100000001> isPrime;
    isPrime.set();// 所有位置1(初始假设都是素数)
    isPrime = isPrime = 0;// 0 和 1 不是素数

    int limit = sqrt(n) + 1;
    for (int i = 2; i <= limit; i++){
      if (isPrime){
            // 从 i*i 开始标记,步长为 i
            for (long long j = (long long)i * i; j <= n; j += i)
                isPrime = 0;
      }
    }

    // 收集所有素数到 vector 中
    vector<int> primes;
    // 预留足够空间(n=1e8内大约有 5~6 百万素数)
    primes.reserve(6000000);
    for (int i = 2; i <= n; i++){
      if (isPrime)
            primes.push_back(i);
    }

    // 对于每个查询,输出第 k 小的素数(k 从1开始计数)
    while(q--){
      int k;
      cin >> k;
      cout << primes << "\n";
    }
    return 0;
}
线性筛
#include <bits/stdc++.h>
using namespace std;

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n, q;
    cin >> n >> q;
    // 使用 vector<bool> 存储标记,空间约 n+1 位(n=1e8约 12.5 MB)
    vector<bool> isComposite(n+1, false);
    vector<int> primes;
    // 预估预留空间(质数数量大约在 5~6 百万左右)
    primes.reserve(n / 10);

    for (int i = 2; i <= n; i++){
      if (!isComposite)
            primes.push_back(i);
      for (int j = 0; j < (int)primes.size() && (long long)primes * i <= n; j++){
            isComposite * i] = true;
            if (i % primes == 0)
                break;
      }
    }

    // 回答每个查询,输出第 k 小的素数(k 从 1 开始)
    while(q--){
      int k;
      cin >> k;
      cout << primes << "\n";
    }
    return 0;
}
 我服了。。。。。风俗性用typedef long long ll;结果一直MLE,到底不知道咋回事的,结果我改成了typedef int ll.就过了。。。。。。
https://i-blog.csdnimg.cn/direct/261c11d191fb471e982804876ab27d91.png
https://i-blog.csdnimg.cn/direct/354093ad9553435c88a24994ed1fa3e2.png
https://i-blog.csdnimg.cn/direct/bf210fdaeaca4926b517391724cdee89.png
 2. 回文质数 Prime Palindromes

关键字(线性筛,埃拉筛,MLE)

https://i-blog.csdnimg.cn/direct/6c865979db29488ebc63ec4c8499e62c.png
 又又又又MMMMMMMMMLLLLLLLLLLLLEEEEEEEEE。。。。。不外又让我知道里一个细节点,有时间内存轻易超限的题少开long long ,用bool比用int来表现vis数组内存开销更小,bitset最小。
埃拉筛。
#include<bits/stdc++.h>
using namespace std;
typedef int ll;

int main(){
        ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
        ll a,b;cin>>a>>b;
        vector<bool> vis(b+1,1);///用int最后一个测试点还是会MLE
        for(ll i=0;i<=b;i++)vis=1;
        for(ll i=2;i<=sqrt(b)+1;i++){
                if(vis==1){
                        for(long long j=1LL*i*i;j<=b;j+=i){
                                vis=0;
                        }
                }
        }
        for(ll i=a;i<=b;i++){
                if(vis==1){
                        string x=to_string(i);
                        string y=x;
                        reverse(x.begin(),x.end());
                        if(x==y)cout<<y<<'\n';
                }
        }
        return 0;
} #include <bits/stdc++.h>
using namespace std;

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    // 读入区间
    int a, b;
    cin >> a >> b;

    // 建立一个 bitset 标记是否为“可能是素数”
    // 下标范围 ,前提: b <= 1e8
    static bitset<100000001> isPrime;
    isPrime.set();         // 初始全设为 1(可能是素数)
    isPrime = 0;          // 0 不是素数
    isPrime = 0;          // 1 不是素数

    // 1) 用埃拉托斯特尼筛在 范围内筛出素数
    int limit = (int)floor(sqrt((long double)b));
    for(int i = 2; i <= limit; i++){
      if(isPrime) {
            // 标记 i*i, i*i + i, ... 都不是素数
            // 用 long long 避免 i*i 溢出
            for(long long j = 1LL * i * i; j <= b; j += i){
                isPrime = 0;
            }
      }
    }

    // 2) 在区间 内,若 isPrime = 1,则 x 是素数
    //    再判断 x 是否回文,如果是就输出
    for(int x = a; x <= b; x++){
      if(isPrime){
            // 检查回文
            string s = to_string(x);
            string r = s;
            reverse(r.begin(), r.end());
            if(s == r){
                cout << s << "\n";
            }
      }
    }

    return 0;
}
 线性筛
#include<bits/stdc++.h>
using namespace std;
typedef int ll;

int main(){
        ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
        ll a,b;cin>>a>>b;
        vector<bool> vis(b+1,0);
        vector<ll> primes;
        primes.reserve(b/10);
        for(ll i=2;i<=b;i++){
                if(vis==0)primes.push_back(i);
                for(ll j=0;(long long)primes*i<=b&&j<primes.size();j++){
                        vis*i]=1;
                        if(i%primes==0){
                                break;
                        }
                }
        }
        for(ll i=a;i<=b;i++){
                if(vis==0){//注意别写错了,别写成vis==1了
                        string x=to_string(i);
                        string y=x;
                        reverse(y.begin(),y.end());
                        if(x==y){
                                cout<<x<<'\n';
                        }
                }
        }
        return 0;
} 3.分解质因子 2 

关键字:(质因数分解)

https://i-blog.csdnimg.cn/direct/c87f71d350ff48b487b056ddb8ae8b37.png
这题更爱MLE。。。。。。。。。什金。。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
        ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
        int t;cin>>t;///用long long会MLE
        while(t--){
                ll n;cin>>n;
                ll t=n;
                for(int i=2;(ll)i*i<=n;i++){///不把i*i强制转化为ll也会MLE
                        while(t%i==0){
                                t/=i;
                                cout<<i<<' ';
                        }
                }
                if(t!=1)cout<<t<<'\n';
                else cout<<'\n';
        }
        return 0;
}
四,高精度加法,减法,乘法,除法

1.A+B Problem

https://i-blog.csdnimg.cn/direct/25901e95c14e443ca2f0ed9cf04785a8.png
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
        ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
        string a,b;cin>>a>>b;
        reverse(a.begin(),a.end());
        reverse(b.begin(),b.end());
        vector<int> aa(a.length());
        vector<int> bb(b.length());
        for(ll i=0;i<a.length();i++)aa=a-'0';
        for(ll i=0;i<b.length();i++)bb=b-'0';
       
        vector<int> ans;
        ll jinwei=0;
        ll cur=0;
        for(ll i=0;i<min(aa.size(),bb.size());i++){
                cur=(aa+bb)+jinwei;
                if(cur>=10)jinwei=1;
                else jinwei=0;
                //jinwei=(aa+bb)/10;
                ans.push_back(cur%10);
        }
        if(aa.size()>bb.size()){
                for(ll i=bb.size();i<aa.size();i++){
                        cur=aa+jinwei;
                        if(cur>=10)jinwei=1;
                        else jinwei=0;
                        ans.push_back(cur%10);
                }
                if(jinwei!=0)ans.push_back(jinwei);
        }else if(aa.size()<bb.size()){
                for(ll i=aa.size();i<bb.size();i++){
                        cur=bb+jinwei;
                        if(cur>=10)jinwei=1;
                        else jinwei=0;
                        ans.push_back(cur%10);
                }
                if(jinwei!=0)ans.push_back(jinwei);
        }else{
                if(jinwei!=0)ans.push_back(jinwei);
        }
        for(ll i=ans.size()-1;i>=0;i--)cout<<ans;
        return 0;
}


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 蓝桥杯自我复习打卡