B 題過的有些牽強,浪費了不少時間,這種題必定想好思路和邊界條件再打,爭取一發過。
D 題最開始讀錯題,後面最後發現能夠重複感受就無法作了,如今想來,數據量大,可是數據範圍小
枚舉不行,二分仍是能夠的,仍是本身的二分水平太差了,平時週一到週四作CF,週五週末複習CF,學習
新的算法,並抽空進行專項訓練ios
D題的思路其實很簡單,我經過二分一個copy的次數val,這樣我再去用每一個數出現的CNT[i]/val,就是這個數算法
回在T序列中出現多少次,那麼check直接上就行,可是要注意,我須要輸出的不是val,而是序列T,那麼我須要數組
每次跑一下,看是否知足,可是到了邊界條件時,發現已經不知足了,可是這時ans數組已經改變,不過不要擔憂,咱們只須要一直把知足條件的val維護就行。最後的時候再跑一次check函數就行。ide
D題代碼函數
#include<iostream> #include<stdio.h> #include<string.h> #include<algorithm> #include<math.h> #include<map> using namespace std; const int maxx = 2e5+10; int a[maxx]; int cnt[maxx]; int n,k; int ans[maxx]; int anss; bool check(int val) { int num=0; int tot =1; for (int i=1; i<maxx; i++) { for (int j=val; j<=cnt[i]; j+=val) { num++; ans[tot++]=i; } } if (num>=k)return 1; else return 0; } void fen(int l,int r) { int mid=(l+r)/2; if (l<=r) { if (check(mid)) { anss=mid; fen(mid+1,r); } else { fen(l,mid-1); } } return; } int main() { scanf("%d%d",&n,&k); memset(cnt,0,sizeof(cnt)); for (int i=1; i<=n; i++) { scanf("%d",&a[i]); } int l=1; int r=0x3f3f3f3f; for (int i=1; i<=n; i++) { cnt[a[i]]++; } fen(l,r); check(anss); for (int i=1;i<=k; i++) { if (i!=k)printf("%d ",ans[i]); else printf("%d\n",ans[k]); } return 0; } /* */
後面留坑學習
E題 天天組織一場比賽,後一天的比賽題目數是前一天比賽數目的兩倍,而且天天的題目必須是同樣,而且第一天題目能夠本身選,問最大選題的數目是多少。spa
這道題我最開始理解錯題意了,後來而後也沒有想到,最後讀懂題目,發現沒辦法作。其實咱們發現,要把次數用map統計,這並無什麼問題,而後把這些值進行離散化,也就是把每種數存下來就行。而後再用一個數組存這些數出現的次數,排序,而後用low_bound查找須要次數。最後遞增就行3d
給出n道有類型的題目,天天組織一場專題比賽,該天題目數量必須是前一天的2倍,第一天的題目數量能夠任意選擇,求能消耗的最多題目數量code
1 #include<iostream> 2 #include<string.h> 3 #include<stdio.h> 4 #include<algorithm> 5 #include<map> 6 using namespace std; 7 int b_size; 8 int a_size; 9 map<int,int>p; 10 vector<int>a,b; 11 int check(int x) 12 { 13 int sum=0; 14 int pos=0; 15 while(1) 16 { 17 pos=(lower_bound(b.begin()+pos,b.end(),x)-b.begin());//大於或等於val的第一個元素位置 18 if (pos==a_size)break;//若是都比這個數小那麼返回的pos==數組大小 19 pos++; 20 sum+=x; 21 x*=2; 22 } 23 return sum; 24 } 25 int main() 26 { 27 int n; 28 int tmp; 29 int mx=0; 30 p.clear(); 31 scanf("%d",&n); 32 for (int i=1; i<=n; i++) 33 { 34 scanf("%d",&tmp); 35 if (p[tmp]==0) 36 { 37 a.push_back(tmp); 38 } 39 p[tmp]++; 40 mx=max(mx,p[tmp]); 41 } 42 b_size=a_size=a.size(); 43 for(int i=0; i<a_size; i++) 44 { 45 b.push_back(p[a[i]]); 46 } 47 sort(b.begin(),b.end()); 48 int ans=0; 49 for (int i=1; i<=mx; i++) 50 { 51 ans=max(ans,check(i)); 52 } 53 printf("%d\n",ans); 54 return 0; 55 }
F1 簡單DP,用DP[i][j]表明前i位置,選j元素的最大值。blog
轉移方程dp[i][l+1]=max(dp[i][l+1],dp[j][l]+a[i])
表示前i個元素,選取了l+1個元素,咱們須要從這個數的前i-k個元素,選取了l個元素傳遞過來。
代碼以下:
#include<iostream> #include<stdio.h> #include<string.h> #include<algorithm> #define ll long long using namespace std; ll a[245]; ll dp[250][250]; const ll inf = 0x3f3f3f3f; int main() { ll n,k,x; scanf("%lld%lld%lld",&n,&k,&x); { for(int i=1; i<=n; i++) { scanf("%lld",&a[i]); } memset(dp,-inf,sizeof(dp)); dp[0][0]=0; //dp[i][j]前i個選出j個 for(int i=1; i<=n; i++)//前i個選出l+1個 { for(int j=i-1; j>=max((ll)0,i-k); j--)//從前i-k位到i-1位,選出l個加上i位置選出a[i] { for(int l=0; l<x; l++) dp[i][l+1]=max(dp[i][l+1],dp[j][l]+a[i]); } } ll maxn; maxn=-1; for (int i=n; i>n-k; i--) { maxn=max(dp[i][x],maxn); } printf("%lld\n",maxn); } return 0; }