hdu--5666--Segment


Segment

 
 Accepts: 418
 
 Submissions: 2020
 Time Limit: 2000/1000 MS (Java/Others)
 
 Memory Limit: 65536/65536 K (Java/Others)
问题描述
\ \ \ \    Rivendell非常神,喜欢研究奇怪的问题.

\ \ \ \    今天他发现了一个有趣的问题.找到一条线段x+y=qx+y=q,令它和坐标轴在第一象限围成了一个三角形,然后画线连接了坐标原点和线段上坐标为整数的格点.

\ \ \ \    请你找一找有多少点在三角形的内部且不是线段上的点,并将这个个数对PP取模后告诉他.
输入描述
\ \ \ \    第一行一个数T,为测试数据组数.

\ \ \ \    接下来每一行两个数qq,PP,意义如题目中所示.

\ \ \ \ q    q是质数且q\le 10^{18},1\le P\le 10^{18},1\le T \le 10q1018,1P1018,1T10.
输出描述
\ \ \ \    对每组数据,输出点的个数模PP后的值.
输入样例
1
2 107
输出样例
0


标准解释:

考虑一条以(0,0)(0,0)为起点,(x,y)(x,y)为终点的线段上格点的个数(不包含端点时),

一定是gcd(x,y)-1gcd(x,y)1,这个很显然吧.

然后整个网格图范围内的格点数目是\frac {q*(q-1)} 22q(q1).

所以答案就是\frac {q*(q-1)} 2 -2q(q1) 所有线段上的格点的个数.

因为gcd(a,b)=gcd(a,b-a)\ (b>a)gcd(a,b)=gcd(a,ba) (b>a),

所以gcd(x,y)=gcd(x,p-x)=gcd(x,p)gcd(x,y)=gcd(x,px)=gcd(x,p),p是质数,所以gcd(x,y)=1gcd(x,y)=1,

所以线段上都没有格点,所以答案就是\frac {q*(q-1)} 22q(q1).

我自己是通过画图看出规律再利用累加的公式退出答案为
\frac {q*(q-1)} 2
2q(q1)

-(q-1)即 (q-1) * (q-2) / 2.

注意是位数太大忘记考虑了!

代码如下:


#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
using namespace std;
#define N 102000
#define inf 0x3f3f3f3f
#define ll long long
ll multiply(ll a, ll b, ll p)
{//快速幂求乘积
	ll sum = 0;
	while (b){
		if (b & 1){
			sum += a;
			sum %= p;
		}
		a *= 2;
		a %= p;
		b >>= 1;
	}
	return sum;
}
int main()
{
#ifdef OFFLINE
	freopen("t.txt", "r", stdin);
#endif
	int i, j, n, t, m;
	ll q, p;
	scanf("%d", &t);
	while (t--){
		scanf("%I64d%I64d", &q, &p);
		//ll num = q*(q - 1) / 2 - (q - 1);
		printf("%I64d\n", multiply(q - 1, q - 2, 2*p) / 2);//p*2才对有点诡异!
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值