数学训练一

博客汇总了多个算法题的解题思路,包括Fibsieve`s Fantabulous Birthday、Knights in Chessboard等题。涉及找规律、博弈、取余防止爆数、约瑟夫环递推等方法,如在博弈题中根据拿取规则和数量取余情况判断胜负。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Fibsieve`s Fantabulous Birthday

思路:找规律

#include<bits/stdc++.h>
using namespace std;
#define int long long
signed main() {
	int T, ca = 1; scanf("%lld", &T);
	while (T--) {
		int t; scanf("%lld", &t);
		int i = sqrt(t), k = 0;
		if (i * i != t)
			i++;
		int x, y;
		k = i * i - (i - 1);
		if (t > k) {
			 x = i * i - t + 1;
			y = i;
		}
		else {
			x = i;
			y = i - (k - t);
		}
        if(i%2!=0)
		    printf("Case %lld: %lld %lld\n", ca++, x, y);
        else
            printf("Case %lld: %lld %lld\n", ca++,y,x);
	}
}

Knights in Chessboard

思路:找规律


A Childhood Game

思路:博弈;Bob先拿就相当于拿到最后的就赢。那么每一轮可以被控制成拿3个,如果数量对三取余不为零那么就是Bob只要把数量mod3的拿完,那么Bob一定能拿到最后一个,因为Bob可以控制每一轮的总数为3;如果数量mod3==0则Alice可以控制每一轮总数为3,Alice可以拿到最后一个。

Alice先拿的话相当于谁拿到到数第二个谁就赢。所以就相当于初始数量减一

#include<bits/stdc++.h>
using namespace std;
int main() {
	int T, ca = 1; cin >> T;
	while (T--) {
		char n[100];
		int t; scanf("%d %s", &t, n);
		if (strcmp(n, "Bob") == 0) {
			if (t % 3 == 0)
				printf("Case %d: Alice\n", ca++);
			else
				printf("Case %d: Bob\n", ca++);
		}
		else {
			if (t % 3 == 1)
				printf("Case %d: Bob\n", ca++);
			else
				printf("Case %d: Alice\n", ca++);
		}
	}
}

Integer Divisibility

思路:每次乘完后对其取余防止爆

#include<bits/stdc++.h>
using namespace std;
#define int long long
signed main() {
	int T, ca = 1; cin >> T;
	while (T--) {
		int n, k; scanf("%lld%lld", &n, &k);
		int ans = 1,c=k;
		while (1) {
			
			if (k % n == 0)
				break;
            k = (k * 10 + c)%n;
			ans++;
		}
		printf("Case %lld: %lld\n", ca++, ans);
	}
}

Ekka Dokka

思路:如果是奇数就不行,之后每次乘二,而不是加,直到变成奇数,如果是加的话比如说‘6’就是可以分解成3*2

#include<bits/stdc++.h>
#define int long long
using namespace std;
signed main() {
	int T, ca = 1; cin >> T;
	while (T--) {
		int n; scanf("%lld", &n);
		int a, b=1;
		if (n % 2 != 0)
			printf("Case %lld: Impossible\n", ca++);
		else {
			while (1) {
				b *= 2;
				a = n / b;
				if (a % 2)
					break;
			}
			printf("Case %lld: %lld %lld\n", ca++, a, b);
		}
	}
}

Mad Counting

思路:每个数字意味着有n+1个人,当n的出现次数每超过了n+1,就说明还有n+1个人

#include<bits/stdc++.h>
using namespace std;
int a[1000000];
int main() {
	int T, ca = 1; cin >> T;
	while (T--) {
		int n, ans = 0; scanf("%d", &n);
		for (int i = 0; i < n; i++) {
			scanf("%d", &a[i]);
		}
		sort(a, a + n);
		int sum=0;
		for (int i = 0; i < n; i++) {
			if (i == 0 || a[i] == a[i - 1])
				sum++;
			else {
				while (sum > 0) {
					ans += a[i - 1] + 1;
					sum -= a[i - 1] + 1;
				}
			}
		}
		while (sum > 0) {
			ans += a[n - 1] + 1;
			sum -= a[n - 1] + 1;
		}
		printf("Case %d: %d\n", ca++, ans);
	}
}

Josephus Problem

思路:约瑟夫环,约瑟夫环的数学优化方法。相当用递推的方法。

#include <bits/stdc++.h>
using namespace std;
int main() {
	int t, n, ans, k,flag = 0;
	scanf("%d", &t);
	while (t--) {
		scanf("%d %d", &n, &k);
		ans = 0;
		for (int i = 2; i <= n; ++i) {
			ans = (ans + k) % i;
		}
		printf("Case %d: %d\n", ++flag, ans + 1);
	}
	return 0;
}

Large Division

思路:大数用数组将其转变为取余

#include<bits/stdc++.h>
using namespace std;
int main() {
	int T, ca = 1; cin >> T;
	while (T--) {
		char a[1000]; long long int b,k=0;
		scanf("%s %lld", a, &b);
		
		int len = strlen(a);
		for (int i = 0; i < len; i++) {
			if (a[0] == '-') {
				a[0] = '0';
			}
			k = (a[i] - '0'+ k) * 10 ;
			k = k % b;
		}
		if (k == 0)
			printf("Case %d: divisible\n", ca++);
		else
			printf("Case %d: not divisible\n", ca++);
	}
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值