注:試題來源於牛客網
1.
牛牛有一個魚缸。魚缸里面已經有n條魚,每條魚的大小為fishSize[i] (1 ≤ i ≤ n,均為正整數),牛牛現在想把新捕捉的魚放入魚缸。魚缸內存在着大魚吃小魚的定律。經過觀察,牛牛發現一條魚A的大小為另外一條魚B大小的2倍到10倍(包括2倍大小和10倍大小),魚A會吃掉魚B。考慮到這個,牛牛要放入的魚就需要保證:1、放進去的魚是安全的,不會被其他魚吃掉2、這條魚放進去也不能吃掉其他魚魚缸里面已經存在的魚已經相處了很久,不考慮他們互相捕食。現在知道新放入魚的大小范圍[minSize,maxSize](考慮魚的大小都是整數表示),牛牛想知道有多少種大小的魚可以放入這個魚缸。
輸入描述:輸入數據包括3行.
第一行為新放入魚的尺寸范圍minSize,maxSize(1 ≤ minSize,maxSize ≤ 1000),以空格分隔。
第二行為魚缸里面已經有魚的數量n(1 ≤ n ≤ 50)
第三行為已經有的魚的大小fishSize[i](1 ≤ fishSize[i] ≤ 1000),以空格分隔。
輸出描述:輸出有多少種大小的魚可以放入這個魚缸。考慮魚的大小都是整數表示
輸入例子:1 12
1
1
輸出例子:3
個人思路:
我是從輸入的魚范圍大小入手,從最小到最大,以此進行判斷。
與魚缸中魚的大小做 /,如果能除盡,就是被吃。反之,則可以增加一次大小。
我的測試用例是 30% case
1 36
1
3
答案輸出 10
我的是 8
魚缸中的一條魚大小是 3,則可放入魚的大小為 2,3,4,5,7,8,10,11,13,14,16,17,19,20,22,23,25,26,28,29,31....
我是真沒弄明白這題的意思。來看看正確答案吧。
分割線:
在分析了一波正確答案之后,我再看題,我明白了,2倍到10倍是一個什么概念!是區間啊大哥。我理解的是,是一個數的2倍,3倍,或者...10倍中的一個。
正確答案(牛客網 id:cheeeenkun):
minSize, maxSize = map(int,raw_input().split())
n = map(int,raw_input())
fishSize = map(int,raw_input().split())
put_in = range(minSize,maxSize+1)
cannot_input = 0
for x in put_in:
flag = 0
for i in fishSize:
if 2*x <= i <=x*10 or i*2 <= x <=i*10:
flag = 1
if flag == 1:
cannot_input += 1
print maxSize+1-minSize-cannot_input
2.
如果一個單詞通過循環右移獲得的單詞,我們稱這些單詞都為一種循環單詞。 例如:picture 和 turepic 就是屬於同一種循環單詞。 現在給出n個單詞,需要統計這個n個單詞中有多少種循環單詞。
輸入描述:輸入包括n+1行:
第一行為單詞個數n(1 ≤ n ≤ 50)
接下來的n行,每行一個單詞word[i],長度length(1 ≤ length ≤ 50)。由小寫字母構成
輸出描述:輸出循環單詞的種數
輸入例子:5
picture
turepic
icturep
word
ordw
輸出例子:2
個人思路:
必須是右移不,這個是相對的例子中,ture是右移的,但是pic就是相對左移那簡單了,先對每一個單詞排序,然后set,最后len(set)當時我是這樣思考的,但測試用例 70% case,錯誤例子:
測試用例:7astatstastsasatstattt對應輸出應該為:3你的輸出為:2
果然我考慮的循環移動是有問題的,沒有徹底思考究竟是什么循環右移。看到一個思路方法:
把要測試的單詞后再重復下這個單詞,如:picture ,變成 picturepicture
然后判斷其他要測試的單詞是不是這個串的子串(長度要先相等)
正確方法(牛客網 id:周昆):
def judge(word1, word2):
if len(word1) != len(word2):
return False
for i in range(len(word1)):
if word1[i:] + word1[:i] == word2:
return True
else:
return False
n = int(raw_input())
rec = list()
for i in range(n):
flag = True
word1 = raw_input()
for word2 in rec:
if judge(word1, word2):
flag = False
break
if flag:
rec.append(word1)
print len(rec)這個貌似就是用了上面思路,通過 python 數組的分割 [3:] [:3] 來進行判斷。就是以此把前面1,2..位的字符放到末尾去
so,循環右移就是把左邊的連續字符移到右邊去即可。
3.
DNA分子是以4種脫氧核苷酸為單位連接而成的長鏈,這4種脫氧核苷酸分別含有A,T,C,G四種鹼基。鹼基互補配對原則:A和T是配對的,C和G是配對的。如果兩條鹼基鏈長度是相同的並且每個位置的鹼基是配對的,那么他們就可以配對合成為DNA的雙螺旋結構。現在給出兩條鹼基鏈,允許在其中一條上做替換操作:把序列上的某個位置的鹼基更換為另外一種鹼基。問最少需要多少次讓兩條鹼基鏈配對成功
輸入描述:輸入包括一行:
包括兩個字符串,分別表示兩條鏈,兩個字符串長度相同且長度均小於等於50。
輸出描述:輸出一個整數,即最少需要多少次讓兩條鹼基鏈配對成功
輸入例子:ACGT TGCA
輸出例子:0
個人思路:
這題是屬簡單題,我這里用了先得出一條鏈的配對鏈,然后去計算另外一條鏈需要變化多少次
正確答案(本人&&牛客網 id:Panzerfaust):
def combine(arr):
wife = []
for a in arr:
if a == 'A':
wife.append('T')
elif a == 'T':
wife.append('A')
elif a == 'C':
wife.append('G')
elif a == 'G':
wife.append('C')
return wife
arr = [s for s in raw_input().strip().split()]
a = list(arr[0])
b = list(arr[1])
c = combine(a)
i = 0
count = 0
while i < len(a):
if c[i] != b[i]:
count += 1
i += 1
print count精簡的代碼;
try:
while 1:
line = raw_input().split()
count =0
tmp = ["AT","TA","GC","CG"]
for i in range(len(line[0])):
if line[0][i]+line[1][i] not in tmp:
count+=1
print(count)
except:
pass這個妙啊,妙啊,妙啊!!!
4.
牛牛的好朋友羊羊在紙上寫了n+1個整數,羊羊接着抹除掉了一個整數,給牛牛猜他抹除掉的數字是什么。牛牛知道羊羊寫的整數神排序之后是一串連續的正整數,牛牛現在要猜出所有可能是抹除掉的整數。例如:10 7 12 8 11 那么抹除掉的整數只可能是95 6 7 8 那么抹除掉的整數可能是4也可能是9
輸入描述:輸入包括2行:
第一行為整數n(1 <= n <= 50),即抹除一個數之后剩下的數字個數
第二行為n個整數num[i] (1 <= num[i] <= 1000000000)
輸出描述:在一行中輸出所有可能是抹除掉的數,從小到大輸出,用空格分割,行末無空格。如果沒有可能的數,則輸出mistake
輸入例子:2
3 6
輸出例子:mistake
個人思路:
我的整體思路就是,先對 n+1 數進行排序,然后從首尾數字入手進行一系列操作即可咯。
哇,就在剛才,我最終還是修改成功了呢。
之前重復的數字,加了一個判斷
另外一個小問題就是必須是正整數
可以的,果然寫博客不錯喲
正確答案(本人&&牛客網 id:Cheeeenkun):
n = int(raw_input())
arr = [int(i) for i in raw_input().strip().split()]
ar = sorted(arr)
first = ar[0]
end = ar[n-1]
middle = n - 2
init = []
result = []
for i in range(first, end+1, 1):
init.append(i)
init_middle = len(init) - 2
if init_middle - middle > 1:
print 'mistake'
elif len(ar) != len(list(set(arr))):
print 'mistake'
else:
if ar == init:
a = ar[0] - 1
if a > 0:
result.append(str(a))
b = ar[n-1] + 1
if b > 0:
result.append(str(b))
else:
i = 0
j = 0
temp = sorted(ar[:])
while i < n and j < len(init):
if temp[i] != init[j]:
if init[j] > 0:
result.append(str(init[j]))
j += 1
else:
i += 1
j += 1
print ' '.join(result)重復數字那里使用 list 和 set,自從會用了這兩個好多問題解決起來很方便。
n = int(raw_input())
numbers_ = map(int,raw_input().split())
max_number = max(numbers_)
min_number = min(numbers_)
result = set(range(min_number,max_number+1))-set(numbers_)
if len(result) == 1:
print list(result)[0]
elif len(result) == 0:
if min_number-1 > 0:
print min_number-1,max_number+1
else:
print max_number+1
elif len(result) > 1:
print 'mistake'這個 ce 大佬前面那題代碼就很妙,哇!還是一個字,太妙了!
亮點在 result = set... 這一句,用 set 集合的關系!哇哇哇!膜拜吧
5.如果一個數字能表示為p^q(^表示冪運算)且p為一個素數,q為大於1的正整數就稱這個數叫做超級素數冪。現在給出一個正整數n,如果n是一個超級素數冪需要找出對應的p,q。
輸入描述:輸入一個正整數n(2 ≤ n ≤ 10^18)
輸出描述:如果n是一個超級素數冪則輸出p,q,以空格分隔,行末無空格。
如果n不是超級素數冪,則輸出No
輸入例子:27
輸出例子:3 3
個人思路:這題我算是誤打誤撞,但還是 40 % case,因為數據太大,時間就超了,而且我只是一個求因子的過程,並沒有判斷素數def yinshi(n):
y = []
i = 2
while i <= n :
if n % i == 0:
n = n / i
y.append(i)
else:
i += 1
return y
n = int(raw_input())
if len(list(set(yinshi(n)))) != 1:
print 'No'
else:
print list(set(yinshi(n)))[0], len(yinshi(n))貌似是不是判斷了素數,我時間也還是超時了。分割線:果然加了素數判斷還是時間問題。
正確答案(牛客網 id:che.jianglin):import math
n = int(raw_input())
l = int(math.log(n,2))
def isPrime(x):
if x<=1:
return False
for i in xrange(2,int(math.sqrt(x))+1):
if x%i==0:
return False
return True
# print(isPrime(3))
flag = True
for i in xrange(2,l+1):
p = math.pow(n,1.0/i)
if(p-int(p)==0 and isPrime(p)):
flag = False
print int(p),i
break;
if(flag):
print "No"果然是數學問題,用了 log 對數函數,然后在用 pow 冪函數。
而我自己問題出在不應該用 while。
6.給出一個正整數N和長度L,找出一段長度大於等於L的連續非負整數,他們的和恰好為N。答案可能有多個,我我們需要找出長度最小的那個。例如 N = 18 L = 2:5 + 6 + 7 = 183 + 4 + 5 + 6 = 18都是滿足要求的,但是我們輸出更短的 5 6 7
輸入描述:輸入數據包括一行:
兩個正整數N(1 ≤ N ≤ 1000000000),L(2 ≤ L ≤ 100)
輸出描述:從小到大輸出這段連續非負整數,以空格分隔,行末無空格。如果沒有這樣的序列或者找出的序列長度大於100,則輸出No
輸入例子:18 2
輸出例子:5 6 7
個人思路:求1 - N-1的連續數列中,和等於N的長度最小數列先從L + 1個長度計算,如果數列中有符合條件的值,則直接輸出這個序列否則的話,L ++繼續求那么,又是時間的問題小的數字都可以完成要求,輸入的數字如果太大,那么就不行。
arr = [int(i) for i in raw_input().strip().split()]
N = arr[0]
L = arr[1]
num = list(xrange(1, N+1))
j = 0
z = 1
k = L + z
add = sum(num[j:k])
while k < len(num):
if add == N:
break
else:
j += 1
k += 1
add = sum(num[j:k])
if k == len(num)-1:
z += 1
k = L + z
j = 0
add = sum(num[j:k])
if add != N or k-j > 100:
print 'No'
else:
m = map(str, num[j:k])
print ' '.join(m)例如:
100 4
18 19 20 21 22
這都是可以完成的。
看到的另外一個思路:
等差數列求和:
S = (2*a1+n-1) / 2
a1 = 2 * S + n - n^2 / 2 *n
n 從 L 到 100 找出滿足的 a1,輸出
嗯,總的來說,就是根據公式來求 a1,然后輸出 a1 之后的 i 即 L 位
哇,我記得當時貌似是有想到等差數列,結果沒太深入想。
正確答案(牛客網 id:Panzerfaust):
import math
import sys
def judge(m,n):
for i in range(n,101):
start = int((2*m/i-i+1)/2)
if int((start+start+i-1)*i/2) == m:
return ' '.join([str(var) for var in range(start,start+i)])
return "No"
for line in sys.stdin:
a = [int(var) for var in line.split()]
print(judge(a[0],a[1]))start = a1
7.
牛牛新買了一本算法書,算法書一共有n頁,頁碼從1到n。牛牛於是想了一個算法題目:在這本算法書頁碼中0~9每個數字分別出現了多少次?
輸入描述:輸入包括一個整數n(1 ≤ n ≤ 1,000,000,000)
輸出描述:輸出包括一行10個整數,即0~9這些數字在頁碼中出現的次數,以空格分隔。行末無空格。
輸入例子:999
輸出例子:189 300 300 300 300 300 300 300 300 300
個人思路:
不得不說,這一題我又是被大整數搞蹦了。而我完全沒想到這樣的算法來解決此題, 我只用了偷雞的方法。
dic = {'1': 0, '2': 0, '3': 0, '4': 0, '5': 0, '6': 0, '7': 0, '8': 0, '9': 0, '0': 0}
page = int(raw_input())
arr = list(xrange(1, page+1))
for a in arr:
num = list(str(a))
for n in num:
dic[n] += 1
print dic['0'], dic['1'], dic['2'], dic['3'], dic['4'], dic['5'], dic['6'], dic['7'], dic['8'], dic['9']和算法相比,我真特么會選方法。
會個P啊會。
正確答案(牛客網 id:zero_python):
num = int(raw_input())
def find(num):
# 計算每個數字, 在每一位上出現的次數.
res = [0] * 10
digit = 1 # 個位
while True:
low = num % digit
cur = (num % (10 * digit)) / digit
high = num / (10 * digit)
if cur == 0 and high == 0:
break
# 各個數字在digit位上出現了幾次?
for i in range(10):
if i < cur:
if i == 0:
res[i] += high * digit
else:
res[i] += (high+1) * digit
elif i == cur:
if i==0:
res[i] += (high-1) * digit + low + 1
else:
res[i] += high * digit + low + 1
else:
if i == 0:
res[i] += (high-1) * digit
else:
res[i] += high * digit
digit *= 10 # 下一位
return res
res = find(num)
print ' '.join(map(str, res))給大家提供一種思路(牛客網 Id: 天祺):
2位數的情況:
N=13,個位數出現的1的次數為2,分別為1和11,十位數出現1的次數為4,分別為10,11,12,13,所以f(N) = 2+4。
N=23,個位數出現的1的次數為3,分別為1,11,21,十位數出現1的次數為10,分別為10~19,f(N)=3+10。
由此我們發現,個位數出現1的次數不僅和個位數有關,和十位數也有關,如果個位數大於等於1,則個位數出現1的次數為十位數的數字加1;如果個位數為0,個位數出現1的次數等於十位數數字。而十位數上出現1的次數也不僅和十位數相關,也和個位數相關:如果十位數字等於1,則十位數上出現1的次數為個位數的數字加1,假如十位數大於1,則十位數上出現1的次數為10。
3位數的情況:
N=123
個位出現1的個數為13:1,11,21,…,91,101,111,121
十位出現1的個數為20:10~19,110~119
百位出現1的個數為24:100~123
我們可以繼續分析4位數,5位數,推導出下面一般情況:
假設N,我們要計算百位上出現1的次數,將由三部分決定:百位上的數字,百位以上的數字,百位一下的數字。
如果百位上的數字為0,則百位上出現1的次數僅由更高位決定,比如12013,百位出現1的情況為100~199,1100~1199,2100~2199,…,11100~11199,共1200個。等於更高位數字乘以當前位數,即12 * 100。
如果百位上的數字大於1,則百位上出現1的次數僅由更高位決定,比如12213,百位出現1的情況為100~199,1100~1199,2100~2199,…,11100~11199,12100~12199共1300個。等於更高位數字加1乘以當前位數,即(12 + 1)*100。
如果百位上的數字為1,則百位上出現1的次數不僅受更高位影響,還受低位影響。例如12113,受高位影響出現1的情況:100~199,1100~1199,2100~2199,…,11100~11199,共1200個,但它還受低位影響,出現1的情況是12100~12113,共14個,等於低位數字13+1。
8.
牛牛正在挑戰一款名為01翻轉的游戲。游戲初始有A個0,B個1,牛牛的目標就是把所有的值都變為1,每次操作牛牛可以任意選擇恰好K個數字,並將這K個數字的值進行翻轉(0變為1,1變為0)。牛牛如果使用最少的操作次數完成這個游戲就可以獲得獎品,牛牛想知道最少的操作次數是多少?例如:A = 4 B = 0 K = 30000 -> 1110 -> 1001 -> 0100 -> 1111需要的最少操作次數為4
輸入描述:輸入為一行:
一共三個整數A(0 ≤ A ≤ 100,000),B(0 ≤ B ≤ 100,000),K(1 ≤ K ≤100,000).以空格分隔
輸出描述:輸出一個整數,表示最少需要的操作次數。如果不能完成,則輸出-1
輸入例子:4 0 3
輸出例子:4
個人思路:
給你說,現在就算是手寫,筆算,自己下去畫,我都不知道怎樣翻轉,你還讓我編程解決。毫無思路。
正確答案(牛客網 id:TinyJian):
本人比較喜歡數學,就從數學的角度來解這道題吧設 n = A+B設 位置值序列集合 E = {e1, e2, e3,... en}, ei ∈ {0, 1},其中ei表示第i個位置上的值 (1 ≤ i ≤ n)假設初始時,前面A個位置為0,后面B個位置為1設 Ti 為 第i個位置上翻轉的次數因為一次翻轉必翻轉K個位置,假設進行了X次翻轉(未知數),則有以下等式① XK = ∑Ti (1 ≤ i ≤ n)因為同一個位置翻轉2次得到是原來的值,所以為了使所有位置均為1, Ti必滿足以下條件:② Ti = 1 + 2Si (ei初始為0)③ Ti = 2Si(ei 初始為1)其中Si表示第i個位置進行了 Si次2次翻轉結合①、②、③可得:④ XK = A + 2 ∑Si (1 ≤ i ≤ n)⑤XK - A 必為偶數我對此的理解為,總的來看:在某些位置上進行了2次翻轉,和A個位置的1次翻轉,就全部為1了。對 ∑Si 觀察可得:對於初始為1的位置,2次翻轉次數不能超過X/2對於初始為0的位置,2次翻轉次數不能超過(X-1)/2 ,因為最后一次翻轉不能屬於“2次翻轉”中的一次翻轉我們假設所有位置的2次翻轉次數都達到最大,則有不等式:⑥ (XK - A)/2 =∑Si (1 ≤ i ≤ n)≤ A ((X-1)/2) + B(X/2)滿足⑤、⑥條件X即可滿足題意我們可以相信,X不能大於 A的最大值+B的最大值 = 200000
PS:我也喜歡數學((┬_┬))