CCPC-Wannafly Comet OJ 夏季欢乐赛(2019)比赛总结
CCPC-Wannafly & Comet OJ 夏季歡樂賽(2019)比賽總結
總結:
? 這場比賽不太順心,B,I水題 10分鐘內A了。A題推公式用double寫卡了1個小時,換成其他暴力也錯了,賽后補題與AC代碼對比發現一個語句的與想象中的不一樣,但是現在還不知道為什么。C題階乘沒想到4!!爆int,一直以為會有個公式,真是大意了導致卡了1個小時。D題是線段樹+掃描線,不熟悉主動放棄。G題想到了每類取前5個然后暴搜,但是算錯時間復雜度了以為會超時就沒寫,不過5分鐘之后想到狀壓dp就給A了。H題分配學號,思路也是比較順利,不過代碼寫完之后有諸多bug(寫錯語句這種低級錯誤),導致比賽結束后也沒A出來,賽后才直到一個變量沒有賦新值,就這樣浪費了一個多小時。
? 總的來的這場比賽小錯誤犯的太多了,打代碼的時候應該再用點心,初始化、語句寫錯等低級錯誤不用犯了。
比賽鏈接:傳送門
題解:
A題完全k叉樹
解決方案:滿層的與根的距離*2+殘缺層的最左邊節點與上一層的距離+最右邊的節點是否可以可以讓答案更遠。
#include<bits/stdc++.h> #define mset(a,b) memset(a,b,sizeof(a)) using namespace std; typedef long long ll; const int inf=0x3f3f3f3f; const double eps=1e-9; int main() {ios::sync_with_stdio(false);cin.tie(0);int t;ll n, k,ans=0;cin>>t;while(t--){cin>>k>>n;if(k==1ll){cout<<n-1ll<<endl;continue;}ll d=0ll,det=1ll,fsum=1ll;while(true){if(det*k+fsum>n) break;d++;det*=k;fsum+=det;}ans=d*2;if(n-fsum>0ll) ans++;if(n-fsum>det) ans++;cout<<ans<<endl;}return 0; }B題距離產生美
解決方案:貪心
#include<bits/stdc++.h> #define mset(a,b) memset(a,b,sizeof(a)) using namespace std; typedef long long ll; ll A[100005]; int main() {int n;ll k;ios::sync_with_stdio(false);cin.tie(0);cin>>n>>k;ll ppp=1e18+10;for(int i=0;i<n;++i) cin>>A[i];int ans=0;for(int i=1;i<n;++i){if(abs(A[i]-A[i-1])<k){ans++;A[i]=ppp;}}cout<<ans<<endl;return 0; }C題烤面包片
解決方案:n>=4的話,n!!的值一定大于mod,結果是0,其他情況暴力求解
#include<bits/stdc++.h> #define mset(a,b) memset(a,b,sizeof(a)) using namespace std; typedef long long ll; ll calc(ll a) {ll ans=1;for(ll i=a; i; --i){ans=ans*i;}return ans; } ll calc(ll a,ll mod) {if(a>=mod) return 0;ll ans=1;for(ll i=a;i;--i){ans=ans*i%mod;if(!ans) return 0;}return ans; } int main() {ios::sync_with_stdio(false);cin.tie(0);ll n,mod;cin>>n>>mod;if(n>=4){cout<<0<<endl;}else if(n==1||n==0){cout<<1%mod<<endl;}else {ll ans=calc(n);ans=calc(ans);ans=calc(ans,mod);cout<<ans%mod<<endl;}return 0;}D題茶顏悅色
解決方案:線段樹+掃描線不會,數據結構靠隊友,沒時間了只能后來再補了
E飛行棋
還沒看題概率dp,先放這,有時間再補吧
F題三元組
解決方案:考慮ai+aj<=bi+bj?a_i+a_j<=b_i+b_j?ai?+aj?<=bi?+bj?? 時候,公式化成2?ai?bi+2?aj+bj<=0?2*a_i-b_i+2*a_j+b_j<=0?2?ai??bi?+2?aj?+bj?<=0?,
否則ai+aj>bi+bja_i+a_j >b_i+b_jai?+aj?>bi?+bj? 時候公式化為2?bi?ai+2?bj+aj<=02*b_i-a_i+2*b_j+a_j<=02?bi??ai?+2?bj?+aj?<=0,考慮到這兩種情況不會同時出現,我們可以分類統計。
先按照第一種情況按2?ai?bi2*a_i-b_i2?ai??bi?的值從到大排序,假如對于i,其符合條件的的最遠的下標為p[i],那么對于i+1,符合條件的最遠的下標在[i+1,p[i]]中,即p[i]不會增大,所以我們可以O(n)雙指針來計算對于每個 i 符合條件的最遠的下標為 p[i]。然后統計貢獻值即可
第二種情況將aia_iai?和bib_ibi?交換然后再按第一種情況統計貢獻值即可
#include<bits/stdc++.h> #define mset(a,b) memset(a,b,sizeof(a)) using namespace std; typedef long long ll; typedef pair<int,int> P; vector<P> comb; map<int,int> mmp; const ll mod=1e9+7; struct Node{ ll a,b,c; bool operator <(const Node & other)const {return (2*a-b)<(other.a*2-other.b); } }; Node tup[100005]; ll presum[100005]; ll getlr(ll l,ll r) {if(r<l) return 0ll;return (presum[r]-presum[l-1])%mod; } ll solve(ll n)//1到n統計個數 {ll ans=0,p=0,r;ll last=tup[1].a*2-tup[1].b;for(ll i=1;i<=n;++i){ll now=tup[i].a*2-tup[i].b;if(last+now<=0)p++,r=i;}ans+=tup[1].c*getlr(1,p);ans%=mod;for(ll i=2;i<=n;++i){last=tup[i].a*2-tup[i].b;while(p>=i&&(last+tup[p].a*2-tup[p].b>0)) p--;ans+=(tup[i].c*getlr(i,p))%mod;ans%=mod;}return ans; } int main() {ios::sync_with_stdio(false);cin.tie(0);ll n;cin>>n;for(ll i=1;i<=n;++i){cin>>tup[i].a>>tup[i].b>>tup[i].c;}sort(tup+1,tup+n+1);for(ll i=1;i<=n;++i){presum[i]=presum[i-1]+tup[i].c;}ll ans=0;ans +=solve(n);for(ll i=1;i<=n;++i) swap(tup[i].a,tup[i].b);sort(tup+1,tup+n+1);for(ll i=1;i<=n;++i){presum[i]=presum[i-1]+tup[i].c;}ans+=solve(n);ans%=mod;cout<<ans<<endl;return 0; }G籃球校賽
解決方案:可以考慮將每類的前5名放在一起去重之后爆搜答案。也考慮考慮狀壓dp,dp[i][s]dp[i][s]dp[i][s] 代表前i個人,位置的狀態的s的最大價值,然后對于第i 個人的每個狀態考慮自己上不上場即可。
#include<bits/stdc++.h> #define mset(a,b) memset(a,b,sizeof(a)) using namespace std; typedef long long ll; ll A[100005][35]; ll dp[100005][35]; int main() {ios::sync_with_stdio(false);cin.tie(0);ll n;cin>>n;for(ll i=1;i<=n;++i){for(ll j=0;j<5;++j) cin>>A[i][j];}ll top=1<<5;for(ll i=1;i<=n;++i){for(ll s=0;s<top;++s){dp[i][s]=dp[i-1][s];for(ll j=0;j<5;++j){ll ns=1<<j;if(!(s&ns)) continue;dp[i][s]=max(dp[i][s],dp[i-1][s^ns]+A[i][j]);}}}cout<<dp[n][top-1]<<endl;return 0;}H題分配學號
解決方案:考慮統計出現的所有學號和出現的次數,然后用rem來表示前面待選的有多個少個,詳情看代碼。
#include<bits/stdc++.h> #define mset(a,b) memset(a,b,sizeof(a)) using namespace std; typedef long long ll; typedef pair<ll,ll> P; vector<P> comb; map<ll,ll> mmp; const ll mod=1e9+7; ll calc(ll a,ll b)//計算階乘A(a,b) {ll ans=1;for(ll k=0;k<b;++k)ans=ans*(a-k)%mod;return ans; } int main() {ios::sync_with_stdio(false);cin.tie(0);ll n;cin>>n;for(ll i=0;i<n;++i){ll x;cin>>x;mmp[x]+=1;}ll lap=-1,lan=-1,rem=0,nwp,nwn;//lap為上一個元素的元號,lan表示上一個元素有多少個,rem表示前面未選位置的的個數for(P p:mmp){nwp=p.first;nwn=p.second;if(lap!=-1){ll dx=nwp-lap;if(rem>dx)//前面未選的的個數大于與前面的學號和該學號間距,放不完,只能放dx個{comb.push_back({rem,dx});//存放A(rem,dx)rem-=dx;rem+=nwn;}else//前面未選的的個數小于與前面的學號和該學號間距,可以放rem個{comb.push_back({rem,rem});rem=nwn;}lap=nwp;lan=nwn;}else{rem=nwn;lap=nwp;lan=nwn;}}comb.push_back({rem,rem});ll ans=1;for(P &p:comb){ans=ans*calc(p.first,p.second)%mod;}cout<<ans<<endl;return 0; }I題Gree的心房
解決方案:水題
#include<bits/stdc++.h> #define mset(a,b) memset(a,b,sizeof(a)) using namespace std; typedef long long ll; ll A[100005]; int main() {ios::sync_with_stdio(false);ll n,m,k;ll ans=0;cin>>n>>m>>k;n--;m--;if(k>m*n) ans=-1;else ans=n+m;cout<<ans<<endl;return 0;}總結
以上是生活随笔為你收集整理的CCPC-Wannafly Comet OJ 夏季欢乐赛(2019)比赛总结的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python实现人脸识别
- 下一篇: tomcat学习笔记(JDK+TOMCA