链接: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;
}