2018C/C++藍橋杯B組省賽
個人理解,僅供參考,歡迎討論
(2)
標題:明碼
漢字的字形存在於字型檔中,即便在今天,16點陣的字型檔也仍然使用廣泛。
16點陣的字型檔把每個漢字看成是16x16個畫素資訊。並把這些資訊記錄在位元組中。
一個位元組可以儲存8位資訊,用32個位元組就可以存一個漢字的字形了。
把每個位元組轉為2進製表示,1表示墨跡,0表示底色。每行2個位元組,
一共16行,佈局是:
第1位元組,第2位元組
第3位元組,第4位元組
....
第31位元組, 第32位元組
這道題目是給你一段多個漢字組成的資訊,每個漢字用32個位元組表示,這裡給出了位元組作為有符號整數的值。
題目的要求隱藏在這些資訊中。你的任務是復原這些漢字的字形,從中看出題目的要求,並根據要求填寫答案。
這段資訊是(一共10個漢字):
4 0 4 0 4 0 4 32 -1 -16 4 32 4 32 4 32 4 32 4 32 8 32 8 32 16 34 16 34 32 30 -64 0
16 64 16 64 34 68 127 126 66 -124 67 4 66 4 66 -124 126 100 66 36 66 4 66 4 66 4 126 4 66 40 0 16
4 0 4 0 4 0 4 32 -1 -16 4 32 4 32 4 32 4 32 4 32 8 32 8 32 16 34 16 34 32 30 -64 0
0 -128 64 -128 48 -128 17 8 1 -4 2 8 8 80 16 64 32 64 -32 64 32 -96 32 -96 33 16 34 8 36 14 40 4
4 0 3 0 1 0 0 4 -1 -2 4 0 4 16 7 -8 4 16 4 16 4 16 8 16 8 16 16 16 32 -96 64 64
16 64 20 72 62 -4 73 32 5 16 1 0 63 -8 1 0 -1 -2 0 64 0 80 63 -8 8 64 4 64 1 64 0 -128
0 16 63 -8 1 0 1 0 1 0 1 4 -1 -2 1 0 1 0 1 0 1 0 1 0 1 0 1 0 5 0 2 0
2 0 2 0 7 -16 8 32 24 64 37 -128 2 -128 12 -128 113 -4 2 8 12 16 18 32 33 -64 1 0 14 0 112 0
1 0 1 0 1 0 9 32 9 16 17 12 17 4 33 16 65 16 1 32 1 64 0 -128 1 0 2 0 12 0 112 0
0 0 0 0 7 -16 24 24 48 12 56 12 0 56 0 -32 0 -64 0 -128 0 0 0 0 1 -128 3 -64 1 -128 0 0
注意:需要提交的是一個整數,不要填寫任何多餘內容。
負數的二進位制等於 原碼取反 再加1 eg:-1 -> 00000001 -> 11111110 ->11111111
利用bitset庫函式一步到位
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <bits/stdc++.h>
typedef long long LL;
const int N =1e5+100;
using namespace std;
typedef long long LL;
const LL mod = 1000000009;
int main()
{
freopen("1.txt","r",stdin);
for(int j=0; j<10; j++)
{
for(int i=0; i<16; i++)
{
for(int k=0; k<2; k++)
{
int x;
cin>>x;
bitset<8>b(x);
string str=b.to_string();
for(int i=0;i<str.length();i++)
{
if(str[i]=='1')cout<<".";
else cout<<" ";
}
}
cout<<endl;
}
}
return 0;
}
手動模擬
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <bits/stdc++.h>
typedef long long LL;
const int N =1e5+100;
using namespace std;
typedef long long LL;
const LL mod = 1000000009;
char str[200][50];
int a[200];
int main()
{
freopen("1.txt","r",stdin);
for(int i=0;i<160;i++)a[i]=0;
int b[10];
int o=0;
for(int j=0; j<10; j++)
{
for(int i=0; i<16; i++,o++)
{
if(j==0&&i==4)
{
int cnt=0;
cnt++;
}
for(int k=0; k<2; k++)
{
//if(j==0)
int x;
scanf("%d", &x);
memset(b,0,sizeof(b));
if(x<0)
{
int h=0;
x=-x;
while(x)
{
int y=x%2;
b[h++]=y;
x/=2;
}
for(int r=7; r>=0; r--)
{
if(b[r]==0)b[r]=1;
else b[r]=0;
}
x=0;
for(int r=7; r>=0; r--) x=x*2+b[r];
x+=1;
memset(b,0,sizeof(b));
h=0;
while(x)
{
int y=x%2;
b[h++]=y;
x/=2;
}
for(int r=7; r>=0; r--)
{
if(r>=0&&b[r]!=0)str[o][a[o]++]='.';
else str[o][a[o]++]=' ';
}
}
else
{
int h=0;
while(x)
{
int y=x%2;
b[h++]=y;
x/=2;
}
for(int r=7; r>=0; r--)
{
if(r>=0&&b[r]!=0)str[o][a[o]++]='.';
else str[o][a[o]++]=' ';
}
}
}
str[o][a[o]++]=' ';
}
}
for(int i=0;i<160;i++)
{
printf("%s\n",str[i]);
if((i+1)%16==0)puts(""),puts("");
}
return 0;
}
(4)
標題:測試次數
x星球的居民脾氣不太好,但好在他們生氣的時候唯一的異常舉動是:摔手機。
各大廠商也就紛紛推出各種耐摔型手機。x星球的質監局規定了手機必須經過耐摔測試,並且評定出一個耐摔指數來,之後才允許上市流通。
x星球有很多高聳入雲的高塔,剛好可以用來做耐摔測試。塔的每一層高度都是一樣的,與地球上稍有不同的是,他們的第一層不是地面,而是相當於我們的2樓。
如果手機從第7層扔下去沒摔壞,但第8層摔壞了,則手機耐摔指數=7。
特別地,如果手機從第1層扔下去就壞了,則耐摔指數=0。
如果到了塔的最高層第n層扔沒摔壞,則耐摔指數=n
為了減少測試次數,從每個廠家抽樣3部手機參加測試。
某次測試的塔高為1000層,如果我們總是採用最佳策略,在最壞的運氣下最多需要測試多少次才能確定手機的耐摔指數呢?
請填寫這個最多測試次數。
注意:需要填寫的是一個整數,不要填寫任何多餘內容。
這題是51nod上的一道原題
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1306
主要要轉換思想,題目問最多需要多少次(就是一定能測出來),轉換為給你一定的物品數量和測試次數能測試的最大高度,即這個高度一定能被測試出來
dp[i][j] (i個物品j次嘗試) dp[i][j]=dp[i-1][j-1]+1+dp[i][j-1];
即在某個高度摔一次碎了,若要一定能測出來那麼這個高度是dp[i-1][j-1]+1
若沒碎即這個高度再加上能測得最大高度dp[i-1][j-1]+1+dp[i][j-1];
這篇部落格說的很清楚一定能看懂 http://blog.sina.com.cn/s/blog_3fe961ae0101llmf.html
(10)標題:乘積最大
給定N個整數A1, A2, … AN。請你從中選出K個數,使其乘積最大。
請你求出最大的乘積,由於乘積可能超出整型範圍,你只需輸出乘積除以1000000009的餘數。
,如果X<0, 我們定義X除以1000000009的餘數是負(-X)除以1000000009的餘數。
即:0-((0-x) % 1000000009)
【輸入格式】
第一行包含兩個整數N和K。
以下N行每行一個整數Ai。
對於40%的資料,1 <= K <= N <= 100
對於60%的資料,1 <= K <= 1000
對於100%的資料,1 <= K <= N <= 100000 -100000 <= Ai <= 100000
【輸出格式】
一個整數,表示答案。
【輸入樣例】
5 3
-100000
-10000
2
100000
10000
【輸出樣例】
999100009
再例如:
【輸入樣例】
5 3
-100000
-100000
-2
-100000
-100000
【輸出樣例】
-999999829
題目是要求解最大最後取模,我給看成取模後解最大。。
把正負數分成兩個陣列處理出來;
判斷結果是正還是負
(1)結果為負數,兩個陣列按絕對值從小到大排序取k個即可
當k=n時,如果負數的個數為奇數一定為負
當k小於n時,只有k取奇數且n個數全為負數結果為負,因為可以通過正負數的個數來調整
(2)結果為正數,兩個陣列按照絕對值從大到小排列,
當k是奇數,先取一個正數,然後每次取一對正數 一對負數比較大小選擇大的
當不夠一對時不選當前陣列
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <bits/stdc++.h>
typedef long long LL;
const int N =1e5+100;
using namespace std;
typedef long long LL;
const LL mod = 1000000009;
LL a[N], b[N];
int cmp(int x,int y)
{
return -x>-y;
}
int cmp1(int x,int y)
{
return x>y;
}
int main()
{
LL n, k;
scanf("%lld %lld", &n, &k);
int k1=0, k2=0;
LL s1=1;
for(int i=0; i<n; i++)
{
LL x;
scanf("%lld", &x);
if(x>=0) a[k1++]=x;
else b[k2++]=x;
s1=s1*x%mod;
}
LL ans=1;
int l1=0, l2=0;
if(k==n) ans=s1;
else if(k1==0&&k%2==1)
{
sort(b,b+k2,cmp1);
for(int i=0; i<k; i++)ans=ans*b[i]%mod;
}
else
{
sort(a,a+k1,cmp1);
if((k&1)&&k1!=0) ans=a[l1++],k--;
while(k>1)
{
LL h1=-1, h2=-1;
if(k1-l1>=1)h1=a[l1]*a[l1+1]%mod;
if(k2-l2>=1)h2=b[l2]*b[l2+1]%mod;
if(h1==-1&&h2==-1)break;
if(h1>h2) ans=ans*h1%mod, l1=l1+2;
else ans=ans*h2%mod, l2=l2+2;
k-=2;
}
}
printf("%lld\n",ans);
return 0;
}