Segment 快速乘(二进制模拟乘)类似于快速

来源:互联网 发布:ug8.5加工编程视频教程 编辑:程序博客网 时间:2024/04/30 17:48

Segment

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1600    Accepted Submission(s): 594


Problem Description
    Silen August does not like to talk with others.She like to find some interesting problems.

    Today she finds an interesting problem.She finds a segment x+y=q.The segment intersect the axis and produce a delta.She links some line between (0,0) and the node on the segment whose coordinate are integers.

    Please calculate how many nodes are in the delta and not on the segments,output answer mod P.
 

Input
    First line has a number,T,means testcase number.

    Then,each line has two integers q,P.

    q is a prime number,and 2q1018,1P1018,1T10.
 

Output
    Output 1 number to each testcase,answer mod P.
 

Sample Input
12 107
 

Sample Output
0
 

Source
BestCoder Round #80
 

Recommend

wange2014



根据题意,是让我们求该直线与第一象限构成的三角形区域中,坐标全为整数点的个数且不包括所连直线的整数点个数,坐标轴上的不算。那么我们可以用区域内的整数点减去所有边上的整数点,就是我们的答案。
1.首先我们求出三角形区域内的整数点,不包括斜边上的点的总个数是,1+2+......+q-2=(q-1)*(q-2)/2.
2.然后我们求出(0,0)与斜边上各整数点的连线上整数点的个数。而(0,0)到(x0,y0)所构成的直线上(除去(x0,y0)外),整数点的个数为gcd(x0,y0)-1.
下面证明一下这个结论...(0,0)到(x0,y0)这条直线方程为y=y0/x0 * x。上下同除以gcd(x0,y0)为,y = (y0/gcd)/(x0/gcd)*x..那么肯定(y0/gcd)与(x0/gcd)是互质的,则y想为整数,则x必须为x0/gcd的整数倍,x范围为0-x0,那么这个区间内的x0/gcd倍数个数为x0/(x0/gcd)=gcd,除去端点(x0,y0),所以为gcd(x0,y0)-1。。。。因此可以推广到一般的情况为(x0,y0)到(x1,y1)构成的直线上,整数点的个数为gcd(x1-x0,y1-y0).


所以我们求出gcd(x0,y0)-1即可,又因为x0+y0=q,且gcd(a,b)=gcd(a,a-b)(a>b)。。所以gcd(x0,y0)=gcd(x0,p-x0)=gcd(x0,p);  p为质数,,那么gcd(x0,p)只可能是p的倍数或者为1,,又因为x,y是小于p的,,,(x+y=p嘛),,所以gcd(x0,p)=gcd(x0,y0)=1.。。。则gcd(x0,y0)-1=0,那么其它直线上是没有整数点的。因此最终的结果就是(q-1)*(q-2)/2.。。


3。注意坑,,q的范围很大,,,(q-1)*(q-2)已经超过long long 了,所以要用到大数知识,,一是用Java的大数类解决,二是用二进制模拟大数乘法得到。。


AC代码:

#include<cstdio>#include<cstring>   #include<algorithm>#include<iostream>#define maxn 55using namespace std;typedef long long ll;ll f(ll a, ll b, ll mod) {ll ans = 0;while(b) {if(b & 1) ans = (ans + a) % mod;a = (a + a) % mod;b >>= 1;}return ans;}int main(){int t;scanf("%d",&t);while(t--) {ll a, b, ans, q, p;scanf("%lld%lld",&q,&p); a = (q-1);b = q - 2;    //这个地方需要判断q的奇偶性,因为要保证 /2 为准确值  if(q & 1)  a /= 2;  //q为奇数,则a为偶数,所以除以2可以整除 else  b /= 2;ans = f(a, b, p);printf("%lld\n",ans);}return 0; } 


0 0
原创粉丝点击