1. 程式人生 > >哈爾濱理工大學第七屆程式設計競賽決賽(網路賽-高年級組)B題幸運大獎

哈爾濱理工大學第七屆程式設計競賽決賽(網路賽-高年級組)B題幸運大獎

幸運大獎

時間限制:C/C++ 1秒,其他語言2秒
空間限制:C/C++ 32768K,其他語言65536K
64bit IO Format: %lld

題目描述

tabris實在是太窮了,為了發財,tabris去買了一張彩票,幸運地中了特別獎。

特別獎是這樣的,不會直接給你發錢.會給你一串二進位制數s,讓你在s中選擇一個不大於k的區間,這個區間表示的數就是獲獎者的獎金數目.

tabris中獎之後已經激動地蒙圈了,他不知道如何選擇能獲得最多的錢,你能幫幫他不?

輸入描述:

輸入一個整數T(T≤10),代表有T組資料.
每組資料佔兩行.
第一行有一個整數K(k≤60),代表tabris能選擇的數字區間的大小.
第二行有一個字串s(∣s∣≤106

).

保證 k≤∣s∣

輸出描述:

輸出一行"Case #x: y",x代表第x組資料,y代表tabris能得到的最多的錢。

示例1

輸入

3

1

10101

3

10101

5

10101

輸出

Case #1: 1

Case #2: 5

Case #3: 21

說明

對於第一個樣例,最大結果為1,選擇 [1]0101,10[1]01,1010[1] 。
對於第二個樣例,最大結果是5,選擇 [101]01,10[101]。
對於第三個樣例,最大結果為21,選擇 [10101]。

題目大意:

中文題目就不解釋,就是選取連續的K位數,使得結果最大

解題思路:

  最先想到暴力,就按照題目的意思模擬,但是感覺會超時。想優化!

發現每次選定k個二進位制數以後往後移動的過程就是左移一位。需要判斷一下最前的一位和最後的一位,需要減去一些數。

最後發現,暴力可以過。按照題目意思做就能過。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<functional>
#define ll long long
using namespace std;

char s[1000005];
int main()
{
	int t;
	int i,j,k;
	int len;
	ll sum,ans,x;
	while(scanf("%d",&t)!=EOF)
	{
		for(i=1;i<=t;i++)
		{
			scanf("%d",&k);	getchar();
			scanf("%s",&s);
			len=strlen(s);
			sum=0; ans=0;
			x=1;
			for(j=k-1;j>=0;j--)//計算前K為二進位制數對應的十進位制數是多少
			{
				sum+=(s[j]-'0')*x;
				x*=2;
			}
			ans=max(ans,sum);
			for(j=k;j<len;j++)//迴圈往後移動
			{
				sum=sum<<1;//左移一位
				if(s[j]=='1')//最後面一位是1
					sum+=1;//需要加上1
				if(s[j-k]=='1')//最前面一位是1
					sum-=x;//需要減去2^k,不然這個數會一直留著,跟在後面移位
				ans=max(ans,sum);
			}
			printf("Case #%d: %lld\n",i,ans);
		}
	}
}
/**
3
3
110110
5
101001111
*/