题目:http://acm.hdu.edu.cn/showproblem.php?pid=5666
题意:给一条直线x+y=q,在(0,0)往x+y=q上面的整数点连线,x+y=q与x,y轴截成的三角形内部,有多少个整数点,除了直线上的点,q是指数。
思路:首先两点之间的整数点有个公式,设A(x1,y1),B(x2,y2),整数点的个数即为gcd(|x1-x2|,|y1-y2|)-1;注意到三角形是一个等腰直角三角形并且三角形在第一象限,所以假设直线x+y=q上面的一个点,C(x,q-x);那么从原点连到这个点上的整数点的个数即为gcd(x,q-x),因为q是质数,设gcd(x,q)=c,那么存在两个互质的数m,n使得m*c=x,n*c=q,那么q-x=(m-n)*c,因为m,n互质,没有任何一个大于一的整数能同时整除这两个数,所以(m-n)跟m还是互质,所以gcd(q-x,x)=gcd(x,q);又因为q是质数,且x<=q,所以gcd(x,q-x)=gcd(x,q)=1,即连线上不会经过三角形内部的点,所以答案就是三角形内部的点的个数,三角形内包括三角形上面的点,一共有(q+1)+(q)+(q-1)+...+1,即(q+2)*(q+1)/2,又因为三角形的边上有3*q个点,所以三角形内部有(q-2)*(q-1)/2个点,好,我以为,这个时候我做完了,最后不就是模P的时候处理一下就好了吗,交一发直接WA,看了一下数据范围:2≤q≤10^18,1≤P≤10^18,1≤T≤10。生无可恋,就算运算的时候取模了还是会爆long long的,用一个大数模板,又一次WA了,最后模仿快速幂的形式写了一个快速积,即边加边取模,过了。。。
代码:
1 #include <stdio.h> 2 #include <iostream> 3 #include <stdlib.h> 4 #include <algorithm> 5 #include <math.h> 6 #include <cstring> 7 using namespace std; 8 long long mul(long long a,long long b,long long mod) 9 { 10 long long ans=0; 11 a%=mod; 12 while(b>0) 13 { 14 if(b%2==1)ans=(ans+a)%mod; 15 b/=2; 16 a=(a+a)%mod; 17 } 18 return ans; 19 } 20 int main() 21 { 22 23 int t; 24 long long int p,q; 25 scanf("%d",&t); 26 while(t--) 27 { 28 29 scanf("%lld %lld",&q,&p); 30 31 long long int ans1=(q-1); 32 long long int ans2=(q-2); 33 if(ans1%2==0) 34 ans1/=2; 35 if(ans2%2==0) 36 ans2/=2; 37 38 printf("%lld ",mul(ans1,ans2,p)); 39 } 40 return 0; 41 }
快速积
1 long long mul(long long a,long long b,long long mod) 2 { 3 long long ans=0; 4 a%=mod; 5 while(b>0) 6 { 7 if(b&1) 8 ans=(ans+a)%mod; 9 a=(a+a)%mod; 10 b>>=1; 11 } 12 return ans; 13 }