4.4省选模拟
\(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;
}