容斥原理
给出一个数N,求1至N中,有多少个数不是2 3 5 7的倍数。 例如N = 10,只有1不是2 3 5 7的倍数。
Input :输入1个数N(1 <= N <= 10^18)。
Output :输出不是2 3 5 7的倍数的数共有多少。
Sample Input :10
Sample Output :1
容斥原理:先不考虑重叠的情况,把包含于某内容中的所有对象的数目先计算出来,然后再把计数时重复计算的数目排斥出去,使得计算的结果既无遗漏又无重复,这种计数的方法称为容斥原理。
可见该文章帮助理解 容斥
1、对于两个集合的表达式:A∪B =|A∪B| = |A|+|B| - |A∩B |
2、三个集合:|A∪B∪C| = |A|+|B|+|C| - |A∩B| - |B∩C| - |C∩A| + |A∩B∩C|
3、四个集合:|A∪B∪C∪D| = |A|+|B|+|C|+|D| - |A∩B| - |A∩C| - |A∩D| - |B∩C| - |B∩D|- |C∩D| + |A∩B∩C|+ |A∩B∩D|+ |A∩C∩D|+ |B∩C∩D| - |A∩B∩C∩D|
#include <stdio.h>
int main(){
long long n ;
// 2 3 5 7
scanf("%lld", &n);
long long count2 = n / 2;
long long count3 = n / 3;
long long count5 = n / 5;
long long count7 = n / 7;
long long count_1 = count2 + count3 + count5 + count7;
long long count23 = n / (2 * 3);
long long count25 = n / (2 * 5);
long long count27 = n / (2 * 7);
long long count35 = n / (3 * 5);
long long count37 = n / (3 * 7);
long long count57 = n / (5 * 7);
long long count_2 = count23 + count25 + count27 + count35 + count37 + count57;
long long count235 = n / (2 * 3 * 5);
long long count237 = n / (2 * 3 * 7);
long long count257 = n / (2 * 5 * 7);
long long count357 = n / (3 * 5 * 7);
long long count_3 = count235 + count237 + count257 + count357;
long long count2357 = n / (2 * 3 * 5 * 7);
long long count_4 = count2357;
long long count = count_1 - count_2 + count_3 -count_4;
printf("%lld\n",n - count);
return 0;
}
Arranging the sheep
输⼊ 组⻓度为 的字符串。其中 . 代表草地, 代表⽺群。每次可以移动⼀只⽺,不可以移出边界。问:最少移动多少步,使得所有的⽺都挨在⼀块。(即⽺与⽺之间没有草地)。*
Input : 第一行包含一个整数t(1≤t≤104)。接下来是测试用例。每个测试用例的第一行包含一个整数n(1≤n≤106)。每个测试用例的第二行包含一个长度为n的字符串,由字符’组成。’(空格)和’*’(羊)——关卡的描述。它保证所有测试用例的n之和不超过106。
Output : 对于每个测试用例,输出完成关卡所需的最小移动数。
Sample Input:
Sample Output :
1
0
0
0
9
使移动次数最少,那就让所有的羊往最终的羊靠拢
1、可以先找出最终件羊的位置,然后从该处分别往左右两边计算到每只羊有多少个空格(空格便是每只羊移动的次数),计算的同时将每只羊的空格数相加,最终结果即所有羊移动的总次数(python)
t = int(input().split()[0])
for i in range(t):
n = int(input().split()[0])
li = input()
low = 0
high = n - 1
flag = 0
mid = 0
while low <= high :
while low <= high :
if li[low] == '.' :
low += 1
else :
flag = 1
mid = low
low += 1
break
while (li[high] == '.') & (low <= high):
high -= 1
high -= 1
if flag == 0:
print(0)
continue
count = 0
low = mid - 1;
count_tmp = 0
while low >= 0:
if li[low] == '.' :
count_tmp += 1
else :
count += count_tmp
low -= 1
high = mid + 1
count_tmp = 0
while high < n:
if li[high] == '.':
count_tmp += 1
else:
count += count_tmp
high += 1
print(count)
2、使用数组记录每只羊的位置,然后再计算(C++)
Ordinary Numbers
如果⼀个数字所有位数都是⼀样的,我们就称它为ordinary number。例如:1 5 99 是,而 100 2021 不是。给定一个数字n,找到1-n之间有多少个这样的数字。
Input : 第一行包含一个整数t(1≤t≤104)。接下来是测试用例。每个测试用例的特征是一个整数n(1≤n≤109)。
Output : 对于每个测试用例,输出从1到n的数字中ordinary number的数量。
Sample Input :
6
1
2
3
4
5
100
Sample Output :
1
2
3
4
5
18
个级别的数字最多有9个,十级别的也有9个,百级别的数字也是9个……也就是说,每一个级别的数字都是有9个ordinarynumber。举一个例子,加入这个数是3234,这个数字有四个级别,个十百级别的都正好各有9个,我们来分析千级别的,3000-4000间ordinary number为3333,而3333比3234大,所以千级别的数字有3-1=2个ordinary number,如果把则个数换成3434,则千级别的ordinary number正好3个。
t = int(input().split()[0])
for i in range(t) :
n = int(input().split()[0])
li = list(str(n))
length = len(li)
if length == 1:
print(n)
continue
li_tmp = [li[0]] * length
num1 = int("".join(li))
num2 = int("".join(li_tmp))
count_tmp = 0
if num1 < num2 :
count_tmp = int(li[0]) - 1
else :
count_tmp = int(li[0])
count = count_tmp + (length - 1) * 9
print(count)
Stone Game
给定一个数组,其中的每个数代表这个石头的大小,现在要求砸碎最大和最小的石头,每次只能从最左边或者最右边开始砸且每次只能砸一个石头,问一共最少需要砸碎多少石头才能把最大和最小的石头都砸碎。
Input : 第一行包含一个整数t(1≤t≤100)。接下来是测试用例。每个测试用例的第一行包含一个整数n(2≤n≤100)——石头的数量。第二行包含n个不同的整数a1,a2,…,an(1≤ai≤n,ai代表石头的大小)。
Output : 对于每个测试用例,输出摧毁具有最大和最小的石头所需的最小次数。
Sample Input :
5
5
1 5 4 3 2
8
2 1 3 4 5 6 8 7
8
4 2 3 1 8 6 7 5
4
3 4 2 1
4
2 3 1 4
Sample Output :
2
4
5
3
2
思路并不复杂,就是代码写的有些绕,因为经常需要判断哪个数更小,使用min函数或者写一个swap可能会更好
首先找出最小和最大的石头的位置,计算一下这两块石头:
(1)要砸到这块石头需要的最小次数
(2)是从左边开始砸还是从右边开始砸的
然后开始砸石头:
(1)若两块石头开始砸的方向是相同的,次数最大的那个就是最终结果
(2)若两块石头开始砸的方向不同:判断先砸较小次数a的那块石头,然后判断一下较大次数b的石头是原本的次数更小还是从a开始砸的次数更小,然后计算砸的总次数即可
t = int(input().split()[0])
for i in range(t) :
n = int(input().split()[0])
li = list(int(x) for x in input().split())
count = 0
length = len(li)
mi = 0
mx = 0
for j in range(1, length) :
if li[j] < li[mi] :
mi = j
if li[j] > li[mx] :
mx = j
if mi + 1 < length - mi:
mi_count = mi + 1
mi_d = 0
else :
mi_count = length - mi
mi_d = 1
if mx + 1 < length - mx:
mx_count = mx + 1
mx_d = 0
else :
mx_count = length - mx
mx_d = 1
if mi_d != mx_d:
if mi_count <= mx_count :
if mx_count <= abs(mx - mi):
count = mi_count + mx_count
else:
count = length - mx_count + 1
else:
if mi_count <= abs(mx - mi):
count = mi_count + mx_count
else:
count = length - mi_count + 1
else :
if mi_count <= mx_count:
count = mx_count
else:
count = mi_count
print(count)
下面是另一个同学的代码,更简洁一些