Codeforces Round #521 (Div. 3) A B C D E
A. Frog Jumping
題目連結:https://codeforces.com/contest/1077/problem/A
題目大意:t組測試資料,從0開始,向前跳a,向後跳b,跳k次,輸出最後所在的位置。
題解:大水題,直接輸出就行了
int main() { std::ios::sync_with_stdio(false); int t; while(cin>>t) { ll a,b,k; for(int i=1;i<=t;++i) { cin>>a>>b>>k; if(k%2) cout<<a*(k/2)-b*(k/2)+a<<endl; else cout<<(a-b)*(k/2)<<endl; } } }
B. Disturbed People
題目連結:https://codeforces.com/contest/1077/problem/B
題目大意:n個數,每個數有0 || 1兩種狀態,0代表關燈睡覺,1代表開燈不睡覺,一個睡覺的如果兩邊都是開著燈的就會不開心(開燈的一直都開心),問最少熄滅多少盞燈能夠讓所有人都開心。
題解:貪心水題,對於每個不開心的人,熄滅後面的那一盞,因為只有後面的那一盞燈會對才會對後面的產生影響。
const int MAXN=2e5+10; const int INF=0x3f3f3f3f; const ll mod=1e9+7; int vis[MAXN]; int main() { std::ios::sync_with_stdio(false); int n; while(cin>>n) { clean(vis,0); for(int i=1;i<=n;++i) cin>>vis[i]; int ans=0; for(int i=1;i<=n;++i) { if(vis[i]==0)//��ס��˯�� { if(vis[i-1]&&vis[i+1])//��ס�������� { ans++; vis[i+1]=0; } } } cout<<ans<<endl; } }
C. Good Array
題目連結:https://codeforces.com/contest/1077/problem/C
題目大意:好陣列的定義是:一個數組裡面存在一個數,使得這個陣列其他元素之和等於該數。我們可以從一個數組中去掉一個數來使它成為一個好陣列,對於每個陣列,輸出所有能夠去掉的一個元素使它能夠構成一個好陣列的元素(一次只能去掉一個)
題解:對於每個陣列,求出它的和 sum,然後對於每個 a[i] 都判斷一次,是否等於(sum-a[i])>>1,不等於則略過,等於則標記,最後輸出即可。
//#pragma comment(linker, "/STACK:1024000000,1024000000") #include<stdio.h> #include<string.h> #include<math.h> //#include<map> //#include<set> #include<deque> #include<queue> #include<stack> #include<bitset> #include<string> #include<fstream> #include<iostream> #include<algorithm> using namespace std; #define ll long long //#define max(a,b) (a)>(b)?(a):(b) //#define min(a,b) (a)<(b)?(a):(b) #define clean(a,b) memset(a,b,sizeof(a))// ˮӡ //std::ios::sync_with_stdio(false); const int MAXN=1e6+10; const int INF=0x3f3f3f3f; const ll mod=1e9+7; int vis[MAXN]; int arr[MAXN]; int ansvis[MAXN]; int main() { std::ios::sync_with_stdio(false); int n; while(cin>>n) { clean(vis,0); clean(arr,0); clean(ansvis,0); ll sum=0; for(int i=1;i<=n;++i) { cin>>arr[i]; sum+=arr[i]; vis[arr[i]]++; } int ans=0; ll res; for(int i=1;i<=n;++i) { res=sum-arr[i];//ȡ����һ���� if(res>2*MAXN) continue; vis[arr[i]]--;//��λ�õ���-- if(vis[res>>1] && res%2==0)//��������� && ����Ҫ�� { ans++; ansvis[i]=1; } vis[arr[i]]++;//�ظ� } if(ans) { cout<<ans<<endl; for(int i=1;i<MAXN;++i) { if(ansvis[i]) cout<<i<<" "; } cout<<endl; } else cout<<0<<endl; } }
D. Cutting Out
題目連結:https://codeforces.com/contest/1077/problem/D
題目大意:給出n個數,這n個數構成一個數組,可以從中提取出無限的有k個元素的陣列,問提取後使原陣列的元素個數最少的k個元素的陣列使什麼,隨便輸出一個就行。
題解:剛拿到題之後比較懵逼,試著用每次都除以二來找。。但是發現不行。。後來考慮用二分出符合要求的迴圈次數,然後遍歷,發現可行,之後又複習了一下二分。。,大概思路就是:對於原陣列,二分出最少的迴圈次數,然後找出符合要求的k個元素
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<math.h>
//#include<map>
//#include<set>
#include<deque>
#include<queue>
#include<stack>
#include<bitset>
#include<string>
#include<fstream>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b)
#define clean(a,b) memset(a,b,sizeof(a))// 水印
//std::ios::sync_with_stdio(false);
const int MAXN=2e5+10;
const int INF=0x3f3f3f3f;
const ll mod=1e9+7;
int arr[MAXN],num[MAXN],ans[MAXN];
int judge(int mid)
{
int res=0;
for(int i=1;i<MAXN;++i)
{
if(num[i]>=mid)
res+=num[i]/mid;//res新加入 num[i]/mid 個元素能重複出現mid輪
}
return res;//res個字元重複出現mid輪
}
int main()
{
std::ios::sync_with_stdio(false);
int n,k;
while(cin>>n>>k)
{
clean(num,0);
clean(ans,0);
for(int i=1;i<=n;++i)
{
cin>>arr[i];
num[arr[i]]++;
}
int l=1,r=n,mid,max_cyc;
while(r>=l)
{
//cout<<mid<<" "<<l<<" "<<r<<endl;
mid=(l+r)>>1;
if(judge(mid)>=k)//res個字元重複出現mid輪 && 能夠輸出k個字元
{//應該輪數更少才行
max_cyc=mid;
l=mid+1;
}
else
r=mid-1;
}
//此時得出的輪數是max_cyc
int tot=0,cyc;
for(int i=1;i<MAXN;++i)
{
cyc=num[i]/max_cyc;
if(cyc>0)
{
for(int j=1;j<=cyc;++j)
{
ans[tot++]=i;
if(tot==k)
break;
}
}
if(tot==k)
break;
}
for(int i=0;i<k;++i)
cout<<ans[i]<<" ";
cout<<endl;
}
}
E. Thematic Contests
題目連結:https://codeforces.com/contest/1077/problem/E
題目大意:給出一個數n,然後是n個數,每個數代表這個問題的種類,要求出一套題,每種問題的個數都是2倍的向上增加的,求出可以選擇的最多的題目數量。
題解:由於ai的資料範圍比較大,所以首先離散化一下資料,然後按照出現的次數排序,在之後,先選最多的,從後往前依次找/2的問題的個數,能找到則加上,找不到則說明這個問題的序列已經到了盡頭,(注意一下,這個數要是偶數,因為如果它是奇數的話,就不能和前面的數構成二倍的關係)
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<map>
//#include<set>
#include<deque>
#include<queue>
#include<stack>
#include<bitset>
#include<string>
#include<fstream>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b)
#define clean(a,b) memset(a,b,sizeof(a))// 水印
//std::ios::sync_with_stdio(false);
const int MAXN=2e5+10;
const int INF=0x3f3f3f3f;
const ll mod=1e9+7;
int arr[MAXN],vis[MAXN];
map<int,int> mp;
int main()
{
std::ios::sync_with_stdio(false);
int n;
while(cin>>n)
{
mp.clear();
clean(arr,0);
clean(vis,0);
for(int i=1;i<=n;++i)
cin>>arr[i];
int k=1;
for(int i=1;i<=n;++i)//資料離散化
{
if(mp[arr[i]]==0)
mp[arr[i]]=k++;
}
for(int i=1;i<=n;++i)//遍歷陣列,將它轉換成出現的次數
vis[mp[arr[i]]]++;
sort(vis,vis+k);//升序遍歷
int ans=0;
for(int i=1;i<=vis[k-1];++i)
{
int choose=k-1;//從後往前找 ,用最多的選上i
int num=i,res=0+num;//一開始選擇i個問題 ,res=0+i
while(num%2==0&&choose>0)
{
num=num>>1;
choose--;
if(vis[choose]<num)
break;
res+=num;
}
ans=max(ans,res);
}
cout<<ans<<endl;
}
}