一些比较弱的数论。。。

辗转相除的思想与运用:

先来道比较水的题目:(spoj 3899)

题目的大意是:给出a,b,x,y,求出最小的q使得 a/b < p/q < x/y,若有多解则求p最小的。

咋一眼看上去没有什么思路。

其实我们可以注意到:y/x < q/p < b/a,也就是说,我们取倒数的话对不等式没有什么影响。

那么我们设[a/b] = k,我们对于每个分数都减去k

我们得出来a',p',x',取倒数后递归解决y/x' < q/p' < b/a'

最后假如当前的a/b < 1,x/y > 1,那么q直接取1就好了。

求出p'之后,q = [p'y/x'] + 1


#include
#include

using namespace std;

typedef long long LL;

LL dfs(LL a,LL b,LL c,LL d)
{
	int i = a / b;
	a -= b * i,c -= d * i;
	if (c > d) return 1;
	if (!a) return d / c + 1;
	LL p = dfs(d,c,b,a);
	return p * d / c + 1;
}

int main()
{
	int a,b,c,d;
	while (scanf("%d %d %d %d", &a, &b, &c, &d) != EOF) 
	{
		LL q = dfs(a,b,c,d);
		printf("%lld/%lld\n",q * a / b + 1,q);
	}
}



      然后一道没这么水的(我觉得而已-_-) (spoj 4717)

题目其实就是给出n,a,b,C,求出sigma(x=0->n)[(ax+C)/b]

是不是觉得很水

我们可以进行一些变形 

当a<b时,

设Y = [ax/b + C],则原式=(sigma(x=0->n)sigma(y=0->Y-1)(y<Y));

交换x,y的位置,原式=(sigma(y=0->Y-1)sigma(x=0->n)(y<Y)

观察当y<Y,时,y < [ax/b + C] -> y + 1 <= [ax/b + C],y + 1 - C <= [ax/b],(y+1-C)*b < [ax]

[(y+1-C)*b-1) / a] < x.

原式=sigma(y=0->Y-1)(n - [((y+1-C)*b-1)/a])

我们成功地将a,b互换了位置!!!然后我们就可以递归求解。

当a>= b时,

原式=sigma(x=0->n)([a/b]x) + sigma(x=0->n)([c/b])+sigma(x=0->n)([((a%b)x+c%b)/b]);

我们继续递归求sigma(x=0->n)([((a%b)x+c%b)/b])

问题就完美解决了。。。

#include
#include
#include

using namespace std;

typedef long long LL;

void read(int &x)
{
	char c;
	while (c = getchar(),c < '0' || c > '9');
	x = c - 48;
	while (c = getchar(),c >= '0' && c <= '9') x = x * 10 + c - 48;
}

int gcd(int a,int b) {return b ? gcd(b,a % b) : a;}

LL Dfs(LL n,LL a,LL b,LL c)
{
	if (!a) return (c / b) * LL(n + 1);
	if (n < 0) return 0;
	if (a >= b) 
	{
		LL tmp = (a / b) * (LL(n) * (n + 1) / 2) + Dfs(n,a % b,b,c % b) + (c / b) * LL(n + 1);
		return tmp;
	} else 
	{
		int Y = (LL(n) * a + c) / b;
		return LL(Y) * n - Dfs(Y - 1,b,a,b - 1 - c);
	}
}	

void Work()
{
	int n,a,b;read(n),read(a),read(b);
	int k = gcd(a,b);a /= k,b /= k;
	printf("%lld\n",Dfs(n,a,b,0) + n + 1);
}

int main()
{
	int T;read(T);
	for(;T;T --) Work();
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值