cf 992C (快速幂模板)【两边端点!!】 992 B 因数

/*

跟我念三遍:考虑端点!考虑端点!考虑端点!

题目的意思就是要么*2 要么*2-1  找规律之后发现其实是连着的 然后就可以递推出表达式,是连着的

啊..  题目有坑,可是什么是坑(以后为了格式直接写网页里面.. 记事本排版太丑-.-)

(1)
【最大和最小 最大和最小】
把1e18考虑到了之后。。
(好像,如果前面样例过了的话一般后面是没什么特别大的问题,但是会,在很大的数据面前跑不出来)
【很多时候我写的代码跑不出来是因为跑不出来,而不是超时了!(什么的)】
而且!!!最小处的坑,可能是 给到了0,或者给到了1
给到了0,或者给到了1(我去找个人改个备注名。。)
(2)
-。-  怎么还会有,取模的是1e9+7,给的是1e9+6这种辣鸡数据-。-。。。。。。。。
【怎么会给取模边界的数据啊啊啊啊!!!!
-。-自己写的数据不对。。
因为,数据给了1e9,乘以2不会有问题,是我多虑了_(:з」∠)_


那么,为什么要取模?
[1]因为给出答案的时候要取模!
[2]前面*2并不会超出范围,然后有的时候会有误差!
有的时候会有误差!
(图片)


... 想想为什么会有取模的误差
这个取模... 
啊。给出的数据是在1e9范围内所以x不用取模,但是乘以2
之后有可能超出题目要求范围
因为一旦有什么可能性就可能溢出。。明白了_(:з」∠)_


x是题目里给的,当然不会溢出啦



↑↑↑写的太乱了。。我不想改了。。

对于992B,很重要的就是最大公约数和最小公倍数。。。代码里都有(x)

copy别人的说明。。:

(参考https://blog.csdn.net/becky_w/article/details/80733056以及https://blog.csdn.net/Haipai1998/article/details/80737815)

题目大意,给你区间[l,r]和x,y 问你区间中有多少个数对 (a,b) 使得 gcd(a,b)=x lcm(a,b)=y 
a,b交换位置就是不同的数对 
1l,r1e9◂,▸1≤l,r≤1⁢e⁢9 and 1x,y<1e9◂,▸1≤x,y<1⁢e⁢9 
题目分析,根据lcm(最小公倍数) 的定义 y=a*b/x; 
也就是说 xy=ab◂=▸x∗y=a∗b 
那么 ,我们发现a,b一定为Y的因数,所以我们枚举y的每个因子就可以,我们只要用log(y)的复杂度暴力算每一个因数就可以 
然后对于每个因子当做a, 
b=x*y/a; 

然后判断a,b是否在区间内,gcd(a,b)是否为x


题意:求区间[L,R]内有多少对数<a,b>,使得gcd(a,b)==x,lcm(a,b)==y.   其中L,R,a,b都已经给定.  如果<a,b>中a==b只算一种

思路:既然是y的因数,可以在sqrt(y)的时间内处理出所有因数个数t(t很小),暴力t^2

关于因数个数很小的解释: 根据质因数分解唯一定理,每个质因数的幂次不会太大,因子总个数=(k1+1)*(k2+1)-----等等.  因此一个数的因子总个数不会太多.碰到类似和因子有关的内容直接暴力


但是自己写的时候遇到一点困难。。。

 因数这里为什么之所以要分开写开 是因为 for (ll i = 1; i*i <= y; i++) 只能算到y的一个因子  而把另一个因子忽略了 如30只能跑到5 而6被人工拿走 所以  记录ll p = y / i;
然后在check里重新算ll  b = x * y / a; 就不会遗漏了_(:з」∠)_


不想写了。。太懒了。。。。。

。。。。。。。。。。。。。打农药去了。。。。

                    18-7-9

*/
【星号】快速幂!
记住快速幂!
//a是底数,b是指数,mode是取模数,sum是记录取模的结果
long long Mode(long long a, long long b, long long mode)
{
long long sum = 1;
while (b) {
if (b & 1) {
sum = (sum * a) % mode;
b--;
}
b /= 2;
a = a * a % mode;
}
return sum;

}

快速幂参考 https://blog.csdn.net/dbc_121/article/details/77646508


#include<iostream>
#include<algorithm>
#include<set>
using namespace std;
typedef long long ll;
const ll modd = 1e9 + 7;


//a是底数,b是指数,mode是取模数,sum是记录取模的结果
long long Mode(long long a, long long b, long long mode)
{
	long long sum = 1;
	while (b) {
		if (b & 1) {
			sum = (sum * a) % mode;
			b--;
		}
		b /= 2;
		a = a * a % mode;
	}
	return sum;
}

int main(){
	ll x; ll k;
	while (cin >> x >> k) {
		// k is the month;
		//k is 1  我怎么把set和mod都忘了..
		if (k == 0)cout << (2 * (x%modd) % modd)<<endl;
		else if (x == 0)cout << 0 << endl;
		else {
			//x = x % modd;
			ll temp = (2 * x - 1) % modd;
			ll summ=Mode(2, k - 1, modd);
			//???? 100*100  在100,00的精度之下不会溢出啊....
			//敏感度吧-.-  100*2没事,100&100也没事,为什么我想了一会高精度算法
			temp = (temp * summ)%modd;
			temp =  (2 * temp + 1) % modd;
			cout << temp << endl;
		}
	}
	return 0;
}

B题

#include<iostream>
#include<algorithm>
#include<set>
#include<math.h>
using namespace std;
typedef long long ll;
const ll modd = 1e9 + 7;
ll a, b, x, y,l,r;
ll gcd(int a, int b)
{
	if (a == 0)		return b;
	else
		return gcd(b % a, a);
}
ll lcm(int a, int b)
{
	return a * b / gcd(a, b);
}
bool check(ll a){//ll b, ll x, ll y) {
ll	 b = x * y / a;//【前面说的就是这里!】
//cout << endl;
//cout << "a " << a << endl;
//cout << "b " << b << endl;
//cout << gcd(a, b) << endl;
//cout << endl;
if (a > r || a < l)return false;
	else if (b > r || b < l)return false;
	else if (gcd(a, b) != x)return false;
	
	//else if (lcm(a, b) != y)return false;
	else return true;
}
int main(){
	while (cin >> l >> r>>x>>y) {
		ll ans = 0;
		//mod 1  寻找质数 记得是i*i  以及要有等号!!
		if (x == y) {
			if (x > r || y < l)cout << "0" << endl;
			else if (x > r || y < l)cout << "0" << endl;
			else cout << "1" << endl;
			return 0;
		}
		for (ll i = 1; i*i <= y; i++) {
			if (y%i == 0) {//如果是0.. 那就是..
				/*
						   //!!!!...
				//a=y/i;
				b = x * y / i;
				//.......  小不忍则乱大谋.......
				///......我能说什么....  这样就忽略了 3 3这种
				//因为自己和自己... 自己不会判断为自己的质数,所以判断不到,所以会少一种
				//我:???? 7和7的因子是7 gcd也是7  ?????
				//????如何想?

咦咦咦.. 代码断片了...

其实不是忽略了30 30 这种呀,面向数据编程但是没有找到症结所在

症结就是两个因子都有可能!

比如3 30这样,我们知道3,30可以,在30,3也加回来了, 然而5 6 这一对

注意到答案是不一样的,5和18不行,6和15可以,6被人为忽略了

很难发现吧。。  但是其实他们俩是不一样 的

				cout << i <<" "<< b << endl;
				if (check(i, b, x, y) == true) {
					ans++;
					if (i != b)ans++;
				}
			}*/
				
				ll p = y / i;
				//cout << "p " << p << endl;
				//cout << "i " << i << endl;
				if (check(i) == true)ans++;
					if (p != i)
				{
						if (check(p) == true)ans++;
				}
			}
			//为什么呢?因为不要给重复的?...
			//test
			//else if (y%i != 0);
		}
		cout << ans << endl;
	}
	return 0;
}




猜你喜欢

转载自blog.csdn.net/strongerirene/article/details/80978228