牛客练习赛38

https://ac.nowcoder.com/acm/contest/358#question

 

A:

给人排个序,比我大的就膜一下,不然跳过。

 

B:

推个公式。利用全概率公式还是贝叶斯公式来着。

 

C:

把状态处理成了字符串。幻方很少,所以预处理出来。从幻方出发,bfs。把所以答案找到。

正确做法是哈希。

我把map和set用了unordered了。卡过

 

#include<iostream>
#include<vector>
#include<string.h>
#include<unordered_set>
#include<unordered_map>

#include<algorithm>
#include<queue>
using namespace std;
#define LL long long

unordered_set<int>mp;
unordered_map<int,int>ans;

int f(int *a){
	int num=0;
	for(int i=1;i<=9;i++){
		num=num*10+a[i];
	}
	return num;
}

queue<pair<int,int> > q;

void init()
{
	int a[10];
	for(int i=1;i<=9;i++)
		a[i]=i;
	do
	{
		int s=a[1]+a[2]+a[3];
		if(a[4]+a[5]+a[6]!=s) continue;
		if(a[7]+a[8]+a[9]!=s) continue;
		if(a[1]+a[4]+a[7]!=s) continue;
		if(a[2]+a[5]+a[8]!=s) continue;
		if(a[3]+a[6]+a[9]!=s) continue;
		if(a[1]+a[5]+a[9]!=s) continue;
		if(a[3]+a[5]+a[7]!=s) continue;
		q.push(make_pair(f(a),0));
		mp.insert(f(a));
	}while(next_permutation(a+1,a+1+9));
}

int dir[12][2]={4,1,4,5,4,7,2,1,2,3,2,5,6,3,6,5,6,9,8,7,8,5,8,9};
//int dir[2][2]={1,2,2,3};

int bfs()
{
	while(!q.empty()){
		pair<int,int> s=q.front();
		q.pop();
		int a[10];
		for(int i=9;i>=1;i--){
			a[i]=s.first%10;
			s.first/=10;
		}
		ans[f(a)]=s.second;
		for(int i=0;i<12;i++){
			swap(a[dir[i][0]],a[dir[i][1]]);
			int to=f(a);
			if(mp.find(to)!=mp.end()){
				swap(a[dir[i][0]],a[dir[i][1]]);
				continue;
			}
			mp.insert(to);
			q.push(make_pair(to,s.second+1));
			swap(a[dir[i][0]],a[dir[i][1]]);

		}
	}
	return -1;
}

int main()
{
	init();
	int T;
	bfs();
	scanf("%d",&T);
	while(T--){
		mp.clear();
		int a[10];
		for(int i=1;i<=9;i++)
		{
			cin>>a[i];
		}
		printf("%d\n",ans[f(a)]);
	}

}

 

 

D:

参考https://blog.csdn.net/Mr_Treeeee/article/details/75675468

 

#include<iostream>
#include<vector>
#include<string.h>
#include<map>
#include<algorithm>
#include<queue>
using namespace std;
#define LL long long
const LL mod = 1000000007;
vector<int>v;
vector<int>vv;

LL getid(LL x) { return lower_bound(v.begin(),v.end(),x)-v.begin()+1;}
LL a[200200];
LL sum[202000];
LL n;
LL num[202000];

LL x[200200];
void add(LL pos)
{
	for(LL i=pos;i<=n;i+=i&-i)
		x[i]++;
}
LL query(LL pos)
{
	LL ans=0;
	for(LL i=pos;i>=1;i-=i&-i)
		ans+=x[i];
	return ans;
}


int main()
{
	cin>>n;
	for(LL i=0;i<n;i++){
		LL x;
		cin>>x;
		v.push_back(x);
	}
	vv=v;
	sort(v.begin(),v.end());v.erase(unique(v.begin(),v.end()),v.end());
	for(LL i=0;i<n;i++){
		a[i]=getid(vv[i]);
		num[a[i]]++;
	}
	sum[0]=0;
	for(LL i=1;i<=n;i++)
		sum[i]=sum[i-1]+num[i];
	LL F=0;
	LL ans=0;
	for(LL i=0;i<n;i++){
		add(a[i]);
		ans+=query(n)-query(a[i]);
		ans%=mod;
	}
	F=ans;
	LL pre=ans;
	for(LL i=0;i<n-1;i++)
	{
		LL now=pre;
		LL xiao=sum[a[i]-1];
		LL da=sum[n]-sum[a[i]];//不包括自己
		pre=(now+da-xiao+mod)%mod;
		F=F*pre%mod;
	}
	cout<<F<<endl;


}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值