您的位置:首页 > 其它

HDU 5666 Segment 数论+大数

2016-04-17 22:55 519 查看

题目链接:

hdu:http://acm.hdu.edu.cn/showproblem.php?pid=5666

bc(中文):http://bestcoder.hdu.edu.cn/contests/contest_chineseproblem.php?cid=688&pid=1002

题解:

首先可以统计出三角形内所有的点数,(q-2)+(q-3)+...+1=(q-1)*(q-2)/2

其次只要减去被线段割到的点,对于线段xi+yi=q,割到的点有gcd(xi,yi)-1=gcd(xi,q-xi)-1=gcd(xi,q)-1;由于q为质数,所以没有没被割到的点。

综上所述,答案为(q-1)*(q-2)/2;

由于(q-1)*(q-2)超过long long 的范围,所以不能直接求解。

以下提供两种解题方案。

1、用java求大数:

import java.util.*;
import java.math.*;
public class Main {
public static void main(String args[]){
Scanner cin = new Scanner(System.in);
long q,P;
int tc=cin.nextInt();

while((tc--)>0){
q=cin.nextLong();
P=cin.nextLong();
BigInteger q1=new BigInteger(Long.toString(q-1));
BigInteger q2=new BigInteger(Long.toString(q-2));
BigInteger ans=q1.multiply(q2);
ans=ans.divide(BigInteger.valueOf(2));
ans=ans.remainder(new BigInteger(Long.toString(P)));
System.out.println(ans.toString());
}
}
}


2、模拟笔算二进制乘法

#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
using namespace std;

const int maxn=1e5+10;
typedef long long LL;

const LL ONE=1;
LL mul(LL a,LL b,LL p){
LL ret=0;
for(;b>0;b>>=1){
if(b&1){
ret+=a;
ret%=p;
}
a=(a+a)%p;
}
return ret;
}

int main() {
int tc;
scanf("%d",&tc);
while(tc--) {
LL q,p;
scanf("%lld%lld",&q,&p);
LL q1=q-1,q2=q-2;
if(q1&1) q2/=2;
else q1/=2;
LL ans=mul(q1,q2,p);
printf("%lld\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: