4.4省選模擬
阿新 • • 發佈:2022-04-04
\(4.4\)省選模擬
狀態提升,感覺很好,今天天氣不錯誒\(\sim\)
\(T1\)
簽到題,直接逐位確定即可
目前\(LOJ\)最優解,洛谷第三
//想到一個基於狀態數的搜尋? //考慮從小到大確定每一位,那麼我們必須每次把最小的處理掉,不然以後就沒法處理了 //這樣的話保證每一次都是合法的 //貌似實現多了一個log,不會消 //算了算了,卡時間 #define Eternal_Battle ZXK #include<bits/stdc++.h> #define INF 2147483647 #define int long long #define MAXN 3005 using namespace std; template<typename T> void read(T &num){ char c=getchar();T f=1;num=0; while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){num=(num<<3)+(num<<1)+(c^48);c=getchar();} num*=f; } vector<int>Fin; multiset<int>s; int Ans[MAXN],Min=INF,cnt,sum,n; void dfs(int now,int ls) { if(now==n+1) { cnt++; for(int i=1;i<=n;i++) { Fin.push_back(Ans[i]); } return ; } Ans[now]=*s.begin()-Ans[1]; if(Ans[now]<=0||Ans[now]<ls) return ; vector<int>Mid; bool flag=true; for(int i=1;i<now;i++) { if(s.find(Ans[now]+Ans[i])!=s.end()) { s.erase(s.lower_bound(Ans[now]+Ans[i])); Mid.push_back(Ans[now]+Ans[i]); } else { flag=false; break; } } if(flag) dfs(now+1,Ans[now]); for(int i=0;i<Mid.size();i++) { s.insert(Mid[i]); } } bool cmp(int a,int b) { return a>b; } signed main() { // freopen("ceobe.in","r",stdin); // freopen("ceobe.out","w",stdout); scanf("%lld",&n); sum=(n-1)*n/2; for(int i=1,num;i<=sum;i++) { read(num); s.insert(num); Min=min(Min,num); } int sum12=Min; int sum13=*(++(++s.begin())); vector<int> Mid; multiset<int>::iterator it=s.begin(); it++;it++;it++; map<int,bool>mp; for(int i=1;i<=n&&it!=s.end();i++) { Mid.push_back(*it); it++; } // dfs(2,Ans[1]=10591472); // return 0; for(int i=0;i<Mid.size();i++) { int del12=sum13-Mid[i]; Ans[1]=(sum12+del12)/2; if(mp[Ans[1]]) continue; mp[Ans[1]]=true; dfs(2,Ans[1]); } printf("%lld\n",cnt); int px[10],num=0; vector<int>Out[10]; for(int i=Fin.size()-n;i>=0;i-=n) { ++num; for(int j=i;j<=i+n-1;j++) { Out[num].push_back(Fin[j]); } px[num]=Out[num][0]; } sort(px+1,px+1+num,cmp); for(int i=1;i<=num;i++) { for(int j=1;j<=num;j++) { if(px[i]==Out[j][0]) { for(int k=0;k<Out[j].size();k++) { printf("%lld ",Out[j][k]); } puts(""); } } } }
\(T2\)
嗯\(\sim\)出題人給了英文題解,讓閱讀理解
一道\(3400\)的紫題(評分機制太怪了)
使用\(Pollard-Rho\)和\(Miller-Rabin\)演算法,再加億點點分類討論(待補)
\(T3\)
奇技淫巧吧,比較顯然的可以\(dp\)
但是我的\(dp\)很像暴力,至於怎麼暴力成正解,\(dalao\ says:\)我們只需保留代價前\(Lim\)位的狀態,就可以保證最後轉移的最優性
正確性不會證明,複雜度不會證明,但是確實能過,好吧,我不會大膽猜想
放一下程式碼,目前\(LOJ\)最劣解。。。
#define Eternal_Battle ZXK #include<bits/stdc++.h> #define int long long #define MAXN 50005 using namespace std; const int Lim=200; vector<pair<int,pair<int,int> > > Sit[2]; int n,L,poz[MAXN]; signed main() { // freopen("my.in","r",stdin); // freopen("my.out","w",stdout); scanf("%lld%lld",&n,&L); for(int i=1;i<=n;i++) { scanf("%lld",&poz[i]); } Sit[0].push_back(make_pair(0,make_pair(0,0))); for(int i=1;i<=n;i++) { int now=i%2; int pre=now^1; Sit[now].clear(); for(int j=0;j<Sit[pre].size();j++) { int ldx=Sit[pre][j].second.first; int ldy=ldx+L; int rdx=Sit[pre][j].second.second; int rdy=rdx+L; int cst=Sit[pre][j].first; if((ldx<=poz[i]&&ldy>=poz[i])||(rdx<=poz[i]&&rdy>=poz[i])) { Sit[now].push_back(make_pair(cst,make_pair(ldx,rdx))); continue; } if(poz[i]>rdy) { Sit[now].push_back(make_pair(cst+poz[i]-rdy,make_pair(ldx,poz[i]-L))); continue; } if(poz[i]<ldx) { Sit[now].push_back(make_pair(cst+ldx-poz[i],make_pair(poz[i],rdx))); continue; } Sit[now].push_back(make_pair(cst+poz[i]-ldy,make_pair(poz[i]-L,rdx))); Sit[now].push_back(make_pair(cst+rdx-poz[i],make_pair(ldx,poz[i]))); } sort(Sit[now].begin(),Sit[now].end()); vector<pair<int,pair<int,int> > >Mid; map<pair<int,int>,bool>mp; for(int j=0;j<Sit[now].size();j++) { if(!mp[make_pair(Sit[now][j].second.first,Sit[now][j].second.second)]) { mp[make_pair(Sit[now][j].second.first,Sit[now][j].second.second)]=true; Mid.push_back(Sit[now][j]); } } swap(Mid,Sit[now]); if(Sit[now].size()>Lim) { sort(Sit[now].begin(),Sit[now].end()); while(Sit[now].size()>Lim) Sit[now].pop_back(); } } sort(Sit[n%2].begin(),Sit[n%2].end()); cout<<Sit[n%2][0].first; }