第十四届浙江财经大学程序设计竞赛 - B - Bazinga (欧几里得+快速幂)

链接:https://www.nowcoder.com/acm/contest/89/B
来源:牛客网

时间限制:C/C++ 3秒,其他语言6秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
题目描述 
There is a formula:

gcd(a, b) is the greatest common divisor of a and b.
Give you three integers L, R and K. Please calculate the value of the following formula:

输入描述:
The first line contains an integer T, where T is the number of test cases. T test cases follow. 
For each test case, the only line contains three integers L, R and K.
• 1 ≤ T ≤ 20.
• 1≤ L ≤ R ≤1018. 
• 1 ≤ K ≤ 105.

输出描述:
For each test case, output one line containing “Case #x: y”, where x is the test case number (starting
from 1) and y is the answer.
示例1
输入

2
1 5 6
10 20 8
输出

Case #1: 5
Case #2: 3
备注:
For the first case, answer = (1×5) mod 6 = 5.
For the second case, answer = (11×13×15×17×19) mod 8 = 3.


题意:

求区间[L,R]内与K互质的数的乘积对K取模后的值


由欧几里得定理gcd(a,b) = gcd(b, a%b)可知 gcd(a, k) = gcd(a+k, k) = ... = gcd(a+n*k, k) = gcd(k, a%k)

且 a*(a+k)*(a+2k)* ... *(a+(n-1)k) % k = a^n % k

得,若a与k互质,则(a+ik)均与k互质

可知每k个为一循环,每个循环内与k互质的数的乘积取模后的值均相同

所以只要判断有几个循环,然后快速幂一下,再乘上循环外的与k互质的数就得到答案了


#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
typedef long long LL;
LL T,l,r,k,cas = 0;
LL gcd(LL a,LL b){return b==0?a:gcd(b,a%b);}
LL qkm(LL n,LL m){
    LL base = n,ans = 1;
    while(m){
        if(m&1) ans = (ans * base) % k;
        base = (base * base) % k;
        m /= 2;
    }
    return ans;
}
int main()
{
    scanf("%lld",&T);
    while(T--){
        scanf("%lld%lld%lld",&l,&r,&k);
        LL cnt = (r-l+1)/k, ans = 1;
        for(LL i=1;i<=k;i++){
            if(gcd(i,k)==1) ans = (ans * i) % k;
        }
        ans = qkm(ans, cnt);
        for(LL i=l+cnt*k;i<=r;i++){
            if(gcd(i%k,k)==1) ans = (ans * (i%k)) % k;
        }
        printf("Case #%lld: %lld\n",++cas,ans % k);
    }
    return 0;
}


猜你喜欢

转载自blog.csdn.net/w326159487/article/details/79834638