第十四届浙江财经大学程序设计竞赛 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.

数论好题!
题意:让你把一个区间内所有和K互质的数相乘,对K取个模。
我们会发现,那些比K大的数字实际上可对K取模再乘起来。而且1~K之间的数字的乘积是确定的,这就意味着我们可以用快速幂来进行一波优化,就是这样啊喵。并不需要什么乘法逆元,我们可以规避除法操作,ojbk。

#include<iostream>
#include<string.h>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<map>
#include<math.h>
using namespace std;
#define ll long long int
const int maxn=1e5+10;
ll L,R,K;
int T;
ll gcd(ll a,ll b){
    if(b==0) return a;
    else return gcd(b,a%b);
}
ll init()
{
  ll ans=1;
    for(ll i=1;i<=K;i++){
        if(gcd(i,K)==1) (ans*=i)%=K;
    }
    return ans;
}
ll qkm(ll a,ll b)
{
    ll ans=1;
    while(b>0){
        if(b%2)
            (ans*=a)%=K;
        (a*=a)%=K;
        b>>=1;
        //cout<<b<<endl;
    }
    return ans;
}
int main()
{
    scanf("%d",&T);int cs=0;
    while(T--){
        scanf("%lld%lld%lld",&L,&R,&K);cs++;
        ll tmp=init();
        ll b=(R/K)-(L/K);    ll ans=1;
        //cout<<b<<endl;
        //cout<<L<<R<<K<<endl;

        //cout<<L<<K<<ans<<endl;
        //cout<<L<<R<<K<<ans<<endl;
        if(b==0){
        for(ll i=L;i<=R;i++){
            if(gcd(i,K)==1) (ans*=i)%=K;
            //cout<<ans<<endl;
        }}
        else{
                b--;
          (ans*=qkm(tmp,b))%=K;
            L%=K;R%=K;tmp=1;
            for(ll i=L;i<=K;i++){
            if(gcd(i,K)==1) (ans*=i)%=K;
            //cout<<ans<<endl;
        }
        for(ll i=1;i<=R;i++){
            if(gcd(i,K)==1) (ans*=i)%=K;
        }
        }
        //cout<<ans<<endl;
        /*for(ll i=1;i<=R;i++){
            if(gcd(i,K)==1) (ans*=i)%=K;
        }*/
        printf("Case #%d: ",cs);
        printf("%lld\n",ans);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值