Acwing202.最幸运的数字(同余)

文章目录

题意

就是给你一个L,问有最少多少个连续的8组成的整数G,使得G%L=0。

思路

这儿参考此大佬的题解
我们设最少x个8能满足上述条件。
G   =   1 0 x − 1 9 × 8 . ∵ G   m o d   L = 0 . ∴ 9 L   ∣   8 × ( 1 0 x − 1 ) G \ = \ \frac{10^x-1}{9} \times 8 \\ . \\ \because G \ mod \ L = 0 \\ .\\ \therefore 9L \ | \ 8 \times (10^x -1) G = 910x1×8.G mod L=0.9L  8×(10x1)
现在我们要将上式子进行进一步化简。我们设 1 0 x − 1 = A 10^x-1 = A 10x1=A,所以 ( 9 L   ∣   8 A ) (9L \ | \ 8A) (9L  8A),因为 g c d ( 8 , 9 ) = 1 gcd(8, 9) = 1 gcd(8,9)=1没有意义,所以我们设 d = g c d ( 8 , L ) d = gcd(8, L) d=gcd(8,L)。于是我们就有 ( 9 L d   ∣   8 d × A ) (\frac{9L}{d} \ | \ \frac{8}{d} \times A) (d9L  d8×A) ,那么现在 g c d ( L d , 8 d ) = g c d ( 9 L d , 8 d ) = 1 gcd(\frac{L}{d}, \frac{8}{d}) = gcd(\frac{9L}{d}, \frac{8}{d}) = 1 gcd(dL,d8)=gcd(d9L,d8)=1,证明 ( 8 d   m o d   9 L d ≠ 0 ) (\frac{8}{d} \ mod \ \frac{9L}{d} \ne 0) (d8 mod d9L=0)但是因为 ( 9 L d   ∣   8 d × A ) (\frac{9L}{d} \ | \ \frac{8}{d} \times A) (d9L  d8×A)始终要成立那么足以说明 ( 9 l d ∣ A ) (\frac{9l}{d} | A) (d9lA)始终成立,那么我们的 8 d \frac{8}{d} d8可以省略,因为 8 d \frac{8}{d} d8对消去 L d \frac{L}{d} dL的质因子没有贡献。如果证明 ( 9 l d ∣ A ) (\frac{9l}{d} | A) (d9lA)我们也可以采用反正法。
那么在上述化简过后我们就得到最终的表达式:
9 L d   ∣   ( 1 0 x − 1 )      < 1 > . C   ∣   ( 1 0 x − 1 )   ( C = 9 L d )    < 2 > \frac{9L}{d} \ | \ (10^x -1) \ \ \ \ <1>\\ . \\C \ | \ (10^x-1) \ (C = \frac{9L}{d}) \ \ <2> d9L  (10x1)    <1>.C  (10x1) (C=d9L)  <2>
接着我们可以把<2>式转化成 1 0 x   m o d   c = 1 10^x \ mod \ c = 1 10x mod c=1 1 0 x ≡ 1   ( m o d   c ) 10^x \equiv 1 \ (mod \ c) 10x1 (mod c)。这里的形式就类似于欧拉定理: a ϕ ( c ) ≡ 1 ( m o d   c )   g c d ( a , c ) = 1 a^{\phi(c)} \equiv 1 (mod \ c) \ gcd(a, c) = 1 aϕ(c)1(mod c) gcd(a,c)=1,但是欧拉定理不能保证 ϕ ( n ) \phi(n) ϕ(n)是满足等式的最小值。那么在一些大佬的题解中看到了一个结论:
满足上述式子的最小正整数x一定是 ϕ ( c ) \phi(c) ϕ(c)的约数,即 x ∣ ϕ ( c ) x | \phi(c) xϕ(c)
反证法证明上述结论:假设该最小正整数x不是 ϕ ( x ) \phi(x) ϕ(x)的约数,则 ϕ ( c ) = k x + r ( 0 < r < x ) \phi(c) = kx+r (0 < r < x) ϕ(c)=kx+r(0<r<x)
{ 1 0 x ≡ 1 ( m o d   c ) ⟹ 1 0 k x ≡ 1 ( m o d   c ) < 3 > 1 0 ϕ ( c ) ≡ 1 ( m o d   c ) ⟹ 1 0 q x + r ≡ 1 ( m o d   c ) < 4 > \left\{\begin{matrix} 10^x \equiv 1(mod \ c) \Longrightarrow 10^{kx} \equiv 1 (mod \ c) &<3>\\ 10^{\phi(c)} \equiv 1 (mod \ c) \Longrightarrow 10^{qx+r} \equiv 1 (mod \ c) & <4> \end{matrix}\right. {10x1(mod c)10kx1(mod c)10ϕ(c)1(mod c)10qx+r1(mod c)<3><4>
由<4>式除以<3>式得 1 0 r ≡ 1 ( m o d   c )   ( 0 < r < x ) 10^r \equiv 1 (mod \ c) \ (0 < r < x) 10r1(mod c) (0<r<x)
因此存在比x更小得正整数解满足上述式子,矛盾,因此得证。
因为我们这儿引用欧拉定理求解那么我们这儿gcd(10, c) = 1,才会有解
而后我们只需要暴力枚举出 ϕ ( c ) \phi(c) ϕ(c)得所有约数,找出满足条件得最小正整数解x即可。
PS:这里我们计算 1 0 i 10^i 10i是可能会爆long long的所以我们这儿采用龟速乘来解决该问题。

代码

#include<bits/stdc++.h>

#define IOS ios::sync_with_stdio(false);cin.tie(nullptr)
#define int long long 
#define endl "\n"
#define xx first
#define yy second

using namespace std;

typedef long long LL;

const int N = 3e6 + 10, mod = 998244353;

int n, m, k, _;

int l;
int gcd(int a, int b){return b ? gcd(b, a%b) : a;}

int get_euler(int c) {
    int res = c;
    for (int i = 2; i <= c / i; ++ i) {
        if (c % i == 0) {
            int s = 0;
            while (c % i == 0) ++ s, c /= i;
            res = res / i * (i - 1);
        }
    }
    if (c > 1) res = res / c * (c - 1);
    return res;
}


LL qmul(LL a, LL b, LL c) { //龟速乘
    LL res = 0;
    while (b) {
        if (b & 1) res = (res + a) % c;
        a = (a + a) % c;
        b >>= 1;
    }
    return res;
}

LL ksm(LL a, LL b, LL c) {
    LL res = 1;
    while (b) {
        if (b & 1) res = qmul(res, a, c);
        a = qmul(a, a, c);
        b >>= 1;
    }
    return res;
}


signed main()
{
   // IOS;
    int T = 1;
    while(cin >> l)
    {
        if(l == 0) break;
        int d = gcd(l, 8);
        int c = 9*l/d;
        int res = 1e18;
        if(gcd(10, c) != 1) res = 0;
        else
        {
            int phi = get_euler(c);

            for(int i = 1; i * i <= phi; i ++)
            {
                if(phi % i == 0)
                {
                    if(ksm(10, i, c) == 1) res = min(res, i);
                    if(ksm(10, phi/i, c) == 1) res = min(res, phi/i);
                }
            }
        }
        
        printf("Case %d: %lld\n", T ++ , res);
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
堆排序是一种高效的排序算法,它利用了堆的数据结构来实现排序。堆是一个完全二叉树,具有以下性质:对于任意节点 i,其父节点的值小于等于子节点的值。 堆排序的基本思路如下: 1. 构建最大堆:将待排序的数组看作是一个完全二叉树,从最后一个非叶子节点开始,依次向上调整每个节点,使得以该节点为根的子树满足最大堆的性质。 2. 将堆顶元素与最后一个元素交换:将最大堆的堆顶元素(即数组的第一个元素)与数组最后一个元素交换位置,此时最大元素就位于数组的最后。 3. 调整堆:将剩余元素重新调整为最大堆。 4. 重复步骤 2 和步骤 3,直到所有元素都排序完成。 以下是堆排序的 C++ 代码实现: ```cpp #include <iostream> using namespace std; // 调整以 root 为根的子树为最大堆 void heapify(int arr[], int n, int root) { int largest = root; // 假设根节点最大 int left = 2 * root + 1; // 左子节点索引 int right = 2 * root + 2; // 右子节点索引 // 若左子节点大于根节点,更新最大值索引 if (left < n && arr[left] > arr[largest]) { largest = left; } // 若右子节点大于最大值节点,更新最大值索引 if (right < n && arr[right] > arr[largest]) { largest = right; } // 若最大值不是根节点,交换根节点和最大值 if (largest != root) { swap(arr[root], arr[largest]); // 递归调整交换后的子树 heapify(arr, n, largest); } } void heapSort(int arr[], int n) { // 构建最大堆 for (int i = n / 2 - 1; i >= 0; i--) { heapify(arr, n, i); } // 逐步取出最大值,调整堆 for (int i = n - 1; i > 0; i--) { swap(arr[0], arr[i]); heapify(arr, i, 0); } } int main() { int arr[] = {4, 10, 3, 5, 1}; int n = sizeof(arr) / sizeof(arr[0]); heapSort(arr, n); cout << "Sorted array: "; for (int i = 0; i < n; i++) { cout << arr[i] << " "; } cout << endl; return 0; } ``` 以上就是堆排序的基本思路和实现方法。堆排序的时间复杂度为 O(nlogn),其中 n 为数组的长度。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值