UVA-OJ.关于数论的成长练习

原创 2015年11月18日 16:21:46

1). UVA11582.Colossal Fibonacci Numbers! 

求斐波那契数列第 ( a ^ b ) 项模 N 的值。

斐波那契数列在模 N 的情况下会有循环节,也就是说当出现连续两项分别等于 F[ 0 ],F[ 1 ] 的时候我们就找到了循环节 T,所以循环节 T 一定在 N ^ 2 的长度内出现。因为 N 比较小,就可以先求出 F[ 1 ] ... F[ N ^ 2 ],然后答案就是 F[ ( a ^ b ) % T ]

#include <cstdio>
#include <cstring>

using namespace std;

typedef unsigned long long ULL;

ULL a, b;
int n, f[1000010];

inline ULL read()
{
	ULL ret = 0; char c = getchar();
	while (!(c >= '0' && c <= '9')) c = getchar();
	while (c >= '0' && c <= '9') ret = ret * 10 + c - '0', c = getchar();
	return ret;
}

void init()
{
	a = read(); b = read();
	scanf("%d", &n);	
}

ULL mul(ULL a, ULL b, int n)
{
	ULL ret = 0;
	while (b){
		if (b & 1) ret = (ret + a) % n;
		a = (2 * a) % n;
		b >>= 1;
	}
	return ret;
}

int power(ULL a, ULL b, int n)
{
	ULL ret = 1;
	a %= n;
	while (b){
		if (b & 1) ret = mul(ret, a, n);
		a = mul(a, a, n);
		b >>= 1;
	}
	return (int)ret;
}

void doit()
{
	int n2 = n * n, r = 2;
	f[0] = 0 % n; f[1] = 1 % n;
	for (int i = 2; i <= n2; i ++){
		f[i] = (f[i - 1] + f[i - 2]) % n;
		if (f[i] == f[1] && f[i - 1] == f[0]){
			r = i - 1;
			break;
		}
	}
	int pos = power(a, b, r);
	printf("%d\n", f[pos] % n);
}

int main()
{
	int T; scanf("%d", &T);
	while (T --){
		init();
		doit();
	}
	return 0;
}

2).UVA12169.Disgruntled Judge

已知递推式 Xi = (a * Xi-1 + b) % 10001,并告诉你 X1,X3, X5 ... X2*t-1,请你求出 X2,X4,X6 ... X2*t

因为递推式模了 10001,所以 a 的取值范围是 [ 0, 10000 ],这样就可以枚举 a。已知了 a ,通过递推式可以推出 X1X3 之间的公式:X3 = ((a ^ 2) * X1 + a * b + b) % 10001,所以 ( a + 1 ) * b % 10001 = (X3 - ( a ^ 2 ) * X1) % 10001。这样就可以用扩展欧几里德求出 b,然后计算 Xi,看是否与已知的 X1,X3 ... X2*t-1 矛盾,如果矛盾则说明 a 不合法,否则就输出出来。

#include <cstdio>

using namespace std;

const int mod = 10001;
typedef long long LL;

int T;
LL s[10005];

void init()
{
	for (int i = 1; i <= T; i ++)
		scanf("%lld", &s[(i << 1) - 1]);
}

void ex_gcd(LL a, LL b, LL &d, LL &x, LL &y)
{
	if (!b){
		x = 1; y = 0; d = a;
		return;
	} else {
		ex_gcd(b, a % b, d, x, y);
		int t = x;
		x = y; y = t - a / b * x;
	}
}

void doit()
{
	s[2] = s[1];
	if(T >= 2){
		for (int a = 0; a <= 10000; a ++){
			LL A = a + 1, B = mod, C = s[3] - a * a * s[1];
			LL x, y, d;
			ex_gcd(A, B, d, x, y);
			if (C % d == 0){
				x = x * (C / d);
				int i;
				for (i = 1; i < T; i ++){	
					s[i << 1] = (s[(i << 1) - 1] * a + x) % mod;
					if (s[(i << 1) + 1] != ((s[i << 1] * a + x) % mod)) break;
				}
				//printf("%d %lld %lld\n", a, x, s[(T << 1) - 1]);
				s[T << 1] = (s[(T << 1) - 1] * a + x) % mod;
				if (i == T) break;
			}
		}
	}
	for (int i = 1; i <= T; i ++) printf("%lld\n", s[i << 1]);
}

int main()
{
	while (scanf("%d", &T) != EOF){
		init();
		doit();
	}
	return 0;
}

3).UVA10375.Choose and divide

求组合数 C(p, q) / C(r, s)

很有趣的题目,还是自己思考比较好,提示一下:唯一分解定理。

#include <cstdio>
#include <cstring>
#include <cmath>

using namespace std;

const int MAX_N = 10005;

int pri[1500], tot = 0;
bool check[MAX_N];
int p, q, r, s, cnt[1500];

inline void prime()
{
	memset(check, 0, sizeof(check));
	check[1] = 1;
	for (int i = 2; i <= 10000; i ++){
		if (!check[i]) pri[++ tot] = i;
		for (int j = 1; j <= tot; j ++){
			if (i * pri[j] > 10000) break;
			check[i * pri[j]] = 1;
			if (i % pri[j] == 0) break; 
		}
	}
}

void gao(int x, int d)
{
	for (int i = 1; i <= tot; i ++){
		while (x % pri[i] == 0){
			x /= pri[i];
			cnt[i] += d;
		}
		if (x == 1) break;
	}
}

void calc(int n, int d)
{
	for (int i = 1; i <= n; i ++)
		gao(i, d);
}
void doit()
{
	memset(cnt, 0, sizeof(cnt));
	calc(p, 1); calc(q, -1); calc(p - q, -1);
	calc(s, 1); calc(r - s, 1); calc(r, -1);
	double ans = 1.0;
	for (int i = 1; i <= tot; i ++)
		ans *= pow(pri[i], cnt[i]);
	printf("%.5f\n", ans);
}

int main()
{
	prime();
	while (scanf("%d%d%d%d", &p, &q, &r, &s) != EOF){
		doit();
	}
	return 0;
}

4).UVA10791.Minimum Sum LCM

输入一个整数 N,求至少两个整数,使得他们的最小公倍数为 N,且这些整数的和最小。输出最小的和。

利用唯一分解定理把 N 分解为 (a1 ^ p1) * (a2 ^ p2) * ... ,不难发现每个 (ai ^ pi) 作为一个单独的整数时最优。但是还有一些陷阱需要处理:N = 1 时答案为 1 + 1 = 2N 只有一种因子时需要加个 1,还要注意 N = 2 ^ 31 - 1 是不要溢出。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>

using namespace std;

const int MAX_N = 1000005;
typedef long long LL;

int p[MAX_N], num[MAX_N], cnt = 0;
LL n;

void doit()
{
	cnt = 0;
	memset(p, 0, sizeof(p)); memset(num, 0, sizeof(num));
	if (n == 1) { printf("2\n"); return; }
	if (n == 2147483647) { printf("2147483648\n"); return; }
	LL t = n;
	for (int i = 2; i * i <= n; i ++){
		if (t % i == 0){
			p[++ cnt] = i;
			while (t % i == 0){
				t /= i;
				num[cnt] ++;
			}
		}
		if (t == 1) break;
	}
	if (t != 1) p[++ cnt] = t, num[cnt] ++;
	if (cnt == 1) {
		LL ans = pow(p[1], num[1]) + 1; printf("%lld\n", ans);
	}
	else {
		LL ans = 0;
		for (int i = 1; i <= cnt; i ++){
			ans += pow(p[i], num[i]);
		}
		printf("%lld\n", ans);
	}
}

int main()
{
	int tot = 0;
	while (cin >> n){
		if (n == 0) break;
		printf("Case %d: ", ++ tot);
		doit(); 
	}
	return 0;
}



 


版权声明:本文为博主原创文章,未经博主允许不得转载。

UVA - 1619 Feel Good(高效算法:滑动窗口)

题意大致是从一个数列里找一个最短的子序列,使得这个子序列的最小值乘这个子序列的和最大。 这道题最关键的地方是找到数列中的某个数在哪个连续序列里是最小的,即这个数的统治区域,一开始我想到的就是输入完之后...
  • qazwer1098
  • qazwer1098
  • 2015年05月03日 17:40
  • 3475

几个有名的在线做题系统(ACM OJ)

1. 浙江大学 Online Judge(ZOJ) http://acm.zju.edu.cn      国内最早也是最有名气的OJ,有很多高手在上面做题。特点是数据比较刁钻,经常会有你想不到的边...
  • chinaliping
  • chinaliping
  • 2013年11月08日 15:43
  • 3472

[uoj228]基础数据结构练习题 解题报告

这题好厉害呀。。看完题一看。。相邻两个数开根号的话差会由a-b变成a√−b√\sqrt a -\sqrt b,相当于除了一个a√+b√\sqrt a+\sqrt b,这样的话很快差就要变成0了,傻逼题...
  • TA201314
  • TA201314
  • 2016年09月11日 16:32
  • 1215

UVA oj 练习水题 算法入门经典(大数系列)

最近做了很多白皮书(算法入门经典)上面的很多水题,但是考验编程的细心还是很考验的,把一些题记录在这儿 424 - Integer Inquiry  代码改的很烂,很不容易的过了: #include ...
  • y990041769
  • y990041769
  • 2013年07月07日 13:18
  • 3565

新视野OJ 2190 [SDOI2008]仪仗队 (数论-gcd)

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2190 题解:让你求0 AC代码: 2190 Accepted 1896 kb...
  • ilovexiaohao
  • ilovexiaohao
  • 2013年10月06日 10:37
  • 1079

【杭电oj】1290 - 献给杭电五十周年校庆的礼物(数论)

点击打开题目 献给杭电五十周年校庆的礼物 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (...
  • wyg1997
  • wyg1997
  • 2016年07月18日 17:30
  • 249

一中OJ #1176 立方数分解[尼科梅彻斯定理] | 数论 + 枚举 | 解题报告

一中OJ | #1176 立方数分解[尼科梅彻斯定理] 时限 1000MS/Case 内存 64MB/Case 题目描述 ...
  • OoLuoChenoO
  • OoLuoChenoO
  • 2017年11月18日 11:53
  • 70

【Light-oj】-1282 - Leading and Trailing(数论,快速幂,log,好)

1282 - Leading and Trailing     PDF (English) Statistics Forum Time Lim...
  • Bear1998
  • Bear1998
  • 2016年08月23日 21:31
  • 150

新视野OJ 2005 [Noi2010]能量采集 (数论-gcd)

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=2005 题解: 设f[i]表示gcd(x,y)=i 的个数(1,其中n=min(n...
  • ilovexiaohao
  • ilovexiaohao
  • 2013年10月06日 12:35
  • 1311

Light OJ 1014 Ifter Party [因子分解]【数论】

题目链接 : http://acm.hust.edu.cn/vjudge/contest/view.action?cid=120197#problem/Q——————————Ifter Party ...
  • qq_33184171
  • qq_33184171
  • 2016年06月29日 15:13
  • 316
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:UVA-OJ.关于数论的成长练习
举报原因:
原因补充:

(最多只允许输入30个字)