HDOJ 5666//快速积,推公式

题目: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,看了一下数据范围:2q10^18,1P10^18,1T10。生无可恋,就算运算的时候取模了还是会爆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\n",mul(ans1,ans2,p));
39     }
40     return 0;
41 }
View Code

快速积

 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 }            
View Code

 

 

posted @ 2016-04-25 14:59  as3asddd  阅读(269)  评论(0编辑  收藏  举报