题目大意:
今天他发现了一个有趣的问题.找到一条线段x+y=q,令它和坐标轴在第一象限围成了一个三角形,然后画线连接了坐标原点和线段上坐标为整数的格点.
请你找一找有多少点在三角形的内部且不是线段上的点,并将这个个数对P取模后告诉他.
思路:考虑一条以(0,0)为起点,(x,y)为终点的线段上格点的个数(不包含端点时),根据相似三角形定理,
与三角形oxy相似的三角形满足底与高的比例为x与y的比例。所以最小三角形为底x/gcd(x,y),高y/gcd(x,y)。
找到这个最小的则按比例乘1,乘2....最多乘gcd(x,y),所以相似三角形个数为 gcd(x,y)。
由于gcd(x,y)=gcd(x,q-x )=gcd(x,q)=1 (q为质数),既这条线不经过内部点,所以答案就是
(q-1)*(q-2)/2 。由于(q-1)*(q-2)会超long long 所以可以用大整数,或者二进制优化。
附java BigInteger代码:
import java.math.BigInteger;
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner in=new Scanner ( System.in );
int t;
t=in.nextInt();
while(t-->0){
BigInteger q,p;
String x;
x=in.next();
q=new BigInteger(x);
x=in.next();
p=new BigInteger(x);
System.out.println( q.subtract( BigInteger.ONE ).multiply(q.subtract( BigInteger.ONE )).subtract(q.subtract( BigInteger.ONE )).divide(BigInteger.valueOf(2)).mod(p) );
}
}
}
二进制优化模板:
ll multi(ll a, ll b, ll p)
{
ll exp = a %p, res = 0;
while (b)
{
if (b & 1) //b的最低位是否为1
{
res = res + exp;
if (res >= p)
res = res -p;
}
exp = exp *2;
if (exp > p)
exp = exp - p;
b >>= 1; //将b除以2
}
return res;
}