1. 程式人生 > >一道題

一道題

str scanf 最大值 sof 輸入 都沒有 color pan tdi

題目

給定一個n 個數的數組A,函數F(x) = a[i] * x的第i 個二進制位。求F 的最大值,x 為整數且0<=x<=n.

輸入格式

第一行一個整數 n 表示數組大小
第二行 n 個整數表示 Ai,Ai 有正有負
接下來一個數 m 的二進制表示,從前到後分別是低位到高位

輸出格式

F(X)的最大值

樣例

輸入:
4
-1 1 2 0
0010
輸出:
2
樣例解釋:
n = 4
f(0) = 0
f(1) = -1; (1 = 1 = 1*a[1])
f(2) = 1 (2 = 01(倒序) = 0*a[1]+1*a[2])
f(3) = 0
f(4) =2

數據範圍:

30% n<=20

100% n<=100000

題解

題目要求將x拆成二進制後,每個位置是1的,加上對應的a數組中的數。

那麽對於30%的數據可以直接枚舉,100%的數據顯然不可以。

然後會發現這樣一個性質:如果每個位置都沒有約束,也就是可以隨便取了,這時可以O(n)的時間算出答案。

之後我們只要創造沒有限制的情況就可以了。

比如對於11001000(正過來了,倒著不舒服)

首先只考慮後三位,如果最後一個1是0的話,這三位隨便取了,O(n)算出答案,註意這個答案需要加上最後一個1前面的的所有價值,不包括最後一個1

之後找到第二個1,同理讓它成為0,算出答案,

這樣其實就是分層處理的,

首先的所有1的價值11001000

之後是 11000000~11000111

10000000~10111111

0~1111111

驚奇的發現每個0~11001000的數全都包含了!

代碼實現:像上面一樣從後往前掃一遍。

註意:一定要開long long,題面居然沒寫a的範圍!!!

開long long與不開的區別是70分!!!

code

 1 /*
 2 開Long Long與不開long long 的區別是70分!!!
 3 */
 4 
 5 #include<cstdio>
 6 #include<algorithm>
 7 #include<cstring>
 8 
 9 using namespace std;
10 11 const int MAXN = 200100; 12 13 long long a[MAXN]; 14 long long m[MAXN]; 15 long long sum = 0,mx = 0,ans,n;//mx誰都不選是0 16 char s[MAXN]; 17 18 inline long long read() { 19 long long x = 0,f = 1;char ch = getchar(); 20 for (; ch<0||ch>9; ch = getchar() ) 21 if (ch==-) f = -1; 22 for (; ch>=0&&ch<=9; ch = getchar()) 23 x = x*10+ch-0; 24 return x*f; 25 } 26 void work(int l,int r) { 27 for (int i=l; i<=r; ++i) { 28 if (a[i] > 0) mx += a[i]; 29 } 30 } 31 int main() { 32 33 34 n = read(); 35 for (int i=1; i<=n; ++i) a[i] = read(); 36 scanf("%s",s); 37 int len = strlen(s); 38 for (int i=0; i<len; ++i) { 39 if (s[i]==1) { 40 m[i+1] = 1;sum += a[i+1]; 41 } 42 else m[i+1] = 0; 43 } 44 ans = sum; 45 long long tmp;int L = 1; 46 for (int i=1; i<=n; ++i) { 47 if (m[i]==1) { 48 sum -= a[i]; 49 work(L,i-1);L = i; 50 tmp = max(mx+sum,mx); 51 ans = max(tmp,ans); 52 } 53 } 54 printf("%lld",ans); 55 return 0; 56 }

清北刷題班 by ccl 函數最值

一道題