Educational Codeforces Round 120 (Rated for Div. 2)
阿新 • • 發佈:2022-01-25
嗚,數學,庫魯西
C. Set or Decrease
題意:給出一組數,可以對每個數進行以下操作:1) 將它-1. 2)將它變成陣列中另一個數。給出k,問至少作多少次操作能使陣列和小於等於k。
解:首先貪心地想,要麼把最小的數變得更小,然後令其他數等於它,要麼每個減1。再想想每個減一沒有讓它變成最小數合算。現在題裡有兩個變數,一是令最小的數減小x,一是將i個數貼上為最小值,直到sum≤k。試圖二分,但這兩個量是關聯的,非線性。試圖三分,但很麻煩,不是每個值都能解。一般這麼麻煩是可以直接算的。算式見程式碼。最後直接列舉每個i,O(n)求解。順帶一提最後表示式寫出來是x+1/x形式,應該是可以三分的qwq
程式碼:
#include<bits/stdc++.h> using namespace std; #define ll long long #define maxx 200005 #define eps 0.00000001 #define inf 0x7fffffff //#define int long long ll n,k; ll a[maxx],sum[maxx]={0}; signed main() { int T; scanf("%d",&T); while(T--){ scanf("%lld%lld",&n,&k); forView Code(int i=1;i<=n;i++) scanf("%lld",&a[i]); sort(a+1,a+n+1); for(int i=1;i<=n;i++) sum[i]=a[i]+sum[i-1]; if(sum[n]<=k) { printf("0\n"); continue; } ll ans=1e18; for(int i=0;i<=n-1;i++){ ll temp=a[1]+ceil(-(k-sum[n-i]+sum[1])/(i+1.0)); if(temp<0) temp=0; ans=min(ans,temp+i); } printf("%lld\n",ans); } return 0; } // suppose that the deletion num is x, and turn i of the n nums to a[1]-x; // (a[1]-x)*(i+1)+sum[2...n-i]<=k // x>=a[1]-((k-sum[2...n-i])/(i+1)) // ans=m+x
D. Shuffle
題意:給出一個01串,每次選一個有k個1的連續區間重新排列組合,問最終有幾種結果。
解:排 列 組 合。顯然每次選擇包含k個1的最長區間先算個組合數,但這樣算下來肯定有重複。考慮重複,假設兩個區間為 ***** ,那麼它們的最大重疊區間會有相同的排列,具體來說,就是從全部重疊個數中選其中1的數量。由於是兩個相鄰區間,所以重疊部分會有k-1個1。注意模數
程式碼:
#include<bits/stdc++.h> using namespace std; #define ll long long #define maxx 5005 #define eps 0.00000001 #define inf 0x7fffffff #define mod 998244353 //#define int long long ll n,k; ll C[maxx][maxx]={0}; ll pos[maxx]={0},cnt=0; char s[maxx]; void init(){ C[0][0]=1; for(int i=1;i<maxx;i++){ C[i][0]=1; for(int j=1;j<maxx;j++) C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod; } } signed main() { init(); scanf("%d%d",&n,&k); scanf("%s",s+1); for(int i=1;i<=n;i++){ if(s[i]=='1') pos[++cnt]=i; } if(k==0||k>cnt){ printf("1\n"); return 0; } ll ans=0; ll front=1; for(int i=1;i<=cnt-k+1;i++){ ll p1=pos[i-1]+1; ll p2=i+k>cnt?n:pos[i+k]-1; ans=(ans+C[p2-p1+1][k])%mod; if(i!=1) ans=(ans+mod-C[pos[i+k-1]-front-1][k-1])%mod; front=pos[i]; } printf("%lld\n",ans); return 0; }View Code