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;
}
posted @ 2022-04-04 20:26  Authentic_k  阅读(25)  评论(0编辑  收藏  举报