XTU 1194 A+B

A+B

     

题目描述

给你三个整数a,b,n。问有多少种只包含a,b的不同序列,使得这个序列的和为n。 例如a=2,b=3,n=7,那么有一种序列:(2+2+3=7,2+3+2=7,3+2+2=7)这三种看作相同,算一种。 例如a=3,b=3,n=6,那么只有一种序列:3+3=6。 例如a=4,b=5,n=7,那么不管a和b怎么排都不会等于7,那么就只有0种序列。

输入

多个样例,每个样例占一行,包括3个整数a,b,n。(0< a,b,n <10^9).直到文件结束。

输出

每个样例输出一行,一个整数,为a,b所能排出的序列数。

样例输入

2 3 7
3 3 6
4 5 7

样例输出

1
1
0


Source

WW

代码:


/**
*  简单扩展欧几里得算法题
*            (注)扩展欧几里得算法原理:
*   x * a+y * b = Gcd(a, b) = Gcd(b,a%b)
*                     = _x * b + _y * a % b
*                     = _x * b +_y * (a – a / b * b)
*                     = _y * a + (_x – _y *a / b) * b
*       所以:  x = _y       y = _x – _y *a / b
*
*   本题思路:利用欧几里得算法求出一组解(x1,y1)
*   通解形式为(x1+k*b, y1-k*a), k为任意整数
*   x1=x*n/g   y1=y*n/g  再通过对a,b,n同时除以g求得x最小整数解
*/
#include <stdio.h>
#define  ll __int64
ll x, y, g;
void ext_gcd(ll a, ll b)
{
	if (b == 0){
		x = 1;
		y = 0;
		g = a;
	}
	else{
		ext_gcd(b, a%b);
		ll temp = x;
		x = y;
		y = temp - a / b*y;
	}
}
int main()
{
	ll a, b, n;
	while (scanf("%I64d%I64d%I64d", &a, &b, &n) != EOF)
	{
		if (a == b){
			if (0 == n%a)
				printf("1\n");
			else
				printf("0\n");
			continue;
		}
		ext_gcd(a, b);
		if (0 != n%g){
			printf("0\n");
			continue;
		}
		x = x*n / g;  //求得x的一个解
		a /= g;
		b /= g;
		n /= g;
		x = x%b;   // 因为x的通解为 x+k*b,所以x的最小整数解为x%b
		if (x < 0)   
			x += b;
		y = (n - a*x) / b;   // 根据公式 a*x + b*y = n
		if (y < 0){
			printf("0\n");
			continue;
		}
		ll k = (n / a - x) / b + 1; // x为最小整数解,a*(x+k*b)<=n 故 k=(n/a - x)/ b + 当k等于0
		printf("%I64d\n", k);
	}
	return 0;
}


你可能感兴趣的:(C++,数论,ACM,扩展欧几里得)