国庆DAY1训练

版权声明:https://github.com/godspeedcurry 欢迎加好友哦 https://blog.csdn.net/qq_38677814/article/details/82917281

J 模拟
题意:移动数字
记录一下每个数字的位置 然后如果和0的距离为1 则交换

#include <bits/stdc++.h>
using namespace std;
struct node
{
	int x,y;	
}p[1020000];
//pos 
int cal(int x,int y){
	return abs(p[x].x-p[y].x)+abs(p[x].y-p[y].y);
}
int a[1020000];
int main(){
	int n,m;
	ios::sync_with_stdio(0);
	cin.tie(0);
	while(cin>>n>>m&&(n||m)){
		int data;
		for(int i = 1; i <= n ; i++ ){
			for(int j =1 ; j <= n ; j++){
				cin>>data;
				p[data].x = i;
				p[data].y = j;	
			}
		}
		while(m--){
			int x;
			cin>>x;
			if(cal(x,0)==1){
				swap(p[x],p[0]);
			}
		}
		for(int i = 0 ; i <= n * n - 1; i++){
			a[(p[i].x-1)*n + p[i].y] = i; 
		}
		for(int i = 1; i <= n * n; i++){
			printf("%d%c",a[i],i==n*n?'\n':' ');
		}
	}
	return 0;
}

A
题意:
find such a x
let a^x + b ^ x = 0 mod p ^k
p is prime and odd
conclusion:
if exist t
a^t + b ^ t = 0 mod p ^ k
a^ pt + b ^ pt = 0 mod p^(k+1)
prove:
let c = a^t:
b^t = (p ^ k )* d - a ^ t
c^p + ( (p ^ k ) * d - c) ^ p
后面那个二项式展开 然后化简一下你会发现可以整除p^(k+1) 的
所以就可以递推了
first
find such a x which
a^x + b ^x = 0 mod p
we can search x of (1~p-1) ( It’s a brute force) to find whether it is true
if doesn’t exist :
ans=-1
else 递推到k次
why not to find more
because we know that a^(p-1) = 1 mod p
so it is enough to find 1~p-1

#include <bits/stdc++.h>
using namespace std;
#define ll long long
ll a,b,p,k;
ll ppow(ll a,ll n){
	ll ret = 1;
	while(n){
		if(n&1) ret = ret*a ;
		a = a*a ;
		n>>=1;
	}
	return ret;
}
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	while(cin>>a>>b>>p>>k){
		ll temp = a;
		ll temp1 = b;
		ll ans = 0;
		for(ll i = 1; i<=p-1 ;i++){
			ll now = (temp + temp1) % p;
			if(now==0){
				ans=i;
				break;
			}
			temp = temp * a % p;
			temp1 = temp1 * b % p;
		}
		if(ans==0){
			printf("-1\n");
		}
		else{
			printf("%lld\n",ppow(p,k-1)*ans);
		}
	}	
	return 0;
}

C
期望题
先求出两个圆相交的概率
设R>=r
固定R 的 位置 分类讨论一下r中轴的位置 根据面积公式求一下面积比 算出概率
最后得出期望即可

n个点可以先sort一下
两两求一下概率

#include <bits/stdc++.h>
using namespace std;
double r[302000];
int main(){
	int n;
	double R;
	cin>>n>>R;
	for(int i=1;i<=n;++i){
		cin>>r[i];
	}
	sort(r+1,r+1+n);
	double ans = 0;
	double sum = 0;
	for(int i = 1 ; i <= n ; i++ ){
		ans += sum * r[i]/R;
		sum += r[i]/R;
	}
	printf("%.10lf\n",ans*2);
	return 0;
}

H
曼哈顿最小生成树
优化可以对每个点求8个象限
求最大边
板子题 板子是求第k条边

#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1000001;
const int INF = 0x3f3f3f3f;
struct Point{
	int x,y,id;
}p[MAXN];
bool cmp(Point a, Point b){
	return a.x!=b.x?a.x<b.x:a.y<b.y;
}
struct BIT{
	int min_val,pos;
	void init(){
		min_val = INF;
		pos = -1;
	}
}bit[MAXN];
struct Edge{
	int u,v,d;
}edge[MAXN<<2];
bool cmpedge(Edge a, Edge b){
	return a.d<b.d;
}
int tot;
int n;
int F[MAXN];
int find(int x){
	if(F[x]==-1)  return x;
	else return F[x]=find(F[x]);
}
void addedge(int u,int v,int d){
	edge[tot].u = u;
	edge[tot].v = v;
	edge[tot++].d = d;
}
int lowbit(int x){
	return x&(-x);
}
void update(int i,int val,int pos){
	while(i){
		if(val<bit[i].min_val){
			bit[i].min_val = val;
			bit[i].pos = pos;
		}
		i -= lowbit(i);
	}
}
int ask(int i,int m){
	int min_val = INF, pos = -1;
	while(i<=m){
		if(bit[i].min_val<min_val){
			min_val = bit[i].min_val;
			pos = bit[i].pos;
		}
		i += lowbit(i);
	}
	return pos;
}
int dist(Point a, Point b){
	return abs(a.x-b.x) + abs(a.y-b.y);
}
void Manhattan_MST(int n,Point p[]){
	int a[MAXN],b[MAXN];
	tot = 0;
	for(int dir = 0; dir<4; dir++){
		if(dir==1||dir==3){
			for(int i=0;i<n;++i){
				swap(p[i].x,p[i].y);
			}
		}
		else if(dir==2){
			for(int i=0;i<n;++i){
				p[i].x = -p[i].x;
			}
		}
		sort(p,p+n,cmp);
		for(int i=0;i<n;++i){
			a[i]=b[i]=p[i].y-p[i].x;
		}
		sort(b,b+n);
		int m = unique(b,b+n)-b;
		for(int i=1;i<=m;++i){
			bit[i].init();
		}
		for(int i=n-1;i>=0;--i){
			int pos = lower_bound(b,b+m,a[i])-b+1;
			int ans = ask(pos,m);
			if(ans!=-1){
				addedge(p[i].id,p[ans].id,dist(p[i],p[ans]));
			}
			update(pos,p[i].x+p[i].y,i);
		}
	}
}
int solve(int k){
	Manhattan_MST(n,p);
	memset(F,-1,sizeof(F));
	sort(edge,edge+tot,cmpedge);
	for(int i=0;i<tot;++i){
		int u = edge[i].u;
		int v = edge[i].v;
		int t1 = find(u),t2=find(v);
		if(t1!=t2){
			F[t1]=t2;
			k--;
			if(k==0) return edge[i].d;
		}
	}
	return 0;
}
int main(){
	while(cin>>n&&n){
		for(int i=0;i<n;++i){
			cin>>p[i].x>>p[i].y;
			p[i].id = i;
		}
		cout<<solve(n-1)<<endl;
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_38677814/article/details/82917281