其他分享
首页 > 其他分享> > 恩偶爱皮模拟尸体-32

恩偶爱皮模拟尸体-32

作者:互联网

水博客太快乐了

RT

考场

又是紧张刺激激动人心的CT报灵赛了。。。

开考先看题,看完三道题感觉没一道可做。。。
感觉凉了。。。

于是决定从 \(T1\) 开始看起。。。。
不会,直接大力线性筛。。。
发现好多无贡献的数也被计算了。。。
于是考虑优化,写了堆优化,两个大样例过了,然后最大的那个跑了将近 \(10s\) 。。。
不管了,先看 \(T2\) \(T3\) 发现都没啥思路,于是写了暴力考虑优化 \(T1\) ,把堆改成了队列,感觉应该会快很多,然而大样例还是跑了 \(3s\) 到 \(4s\)。。。
但是感觉时间复杂度是正确的,常数也小的可怜。。。
不管了,就这样交吧。。。
重新看 \(T2\ T3\) ,深刻地认识到了我什么都不会的事实。。。
于是 \(T2\) 大力 \(xin\ team\) ,\(T3\) 直接骗 \(30pts\) 。。。
感觉冲后两题不如回来优化 \(T1\) 。。。(其实此时 \(T1\) 已经过了。。。。

最后也没有水出什么有用的东西。。。。

分数

预估 : \(t1\ 80pts\ +\ t2\ 20pts\ +\ t3\ 30pts\ =\ 130pts\)
实际 : \(t1\ 100pts\ +\ t2\ 24pts\ +\ t3\ 30pts\ =\ 154pts\)

震惊!!! \(t1\) 居然就这么过了???!!!
后来和巨佬 \(CYH\) 表达了我对 \(A\) 了这题的震惊,得知他本机最大样例不到 \(1s\) 就跑完了。。。是我电脑太卡了???

题解

A. Smooth

乍一看只会暴力,于是写了大力线性筛,发现线性筛的时候有很多数实际上对答案是没有贡献的,与是考虑优化,发现线性筛是将每一个找到的质数都存下来,用来筛之后的数,然而当质数大于 \(p_{b}\) 时,就已经不可能对答案有贡献了,所以只用前 \(b\) 个数筛即可,将筛到的数存到堆或队列里,堆带一个 \(\log\) 所以显然会 \(T\) 。
所以要用队列,用队列为了保证选数时的单调性,必须开 \(b\) 个队列,每次从这 \(b\) 个队列的队头中找一个最小值进行线性筛的操作即可。。。
时间复杂度 \(O(KB)\) ,显然可过。。。

code
#include<bits/stdc++.h>
using namespace std;
const int B=16, K=1e7+10;
const long long MAXN=1e18+5;
inline int read(){
	int f=1, x=0; char ch=getchar();
	while(!isdigit(ch)) { if(ch=='-') f=-1; ch=getchar(); }
	while(isdigit(ch)) { x=x*10+ch-48; ch=getchar(); }
	return f*x;
}
int cnt, b, k, minn;
long long pri[B], u;
bool vis[100];
queue<long long> q[B];
int main(void){
	b=read(), k=read()-1;
	if(!k) { printf("1\n"); return 0; }
	for(int i=2; cnt<b; ++i){
		if(!vis[i]) pri[++cnt]=i;
		for(int j=1; j<=cnt&&i*pri[j]<100; ++j){
			vis[pri[j]*i]=1;
			if(i%pri[j]==0) break;
		}
	}
	for(int i=1; i<=cnt; ++i) q[i].push(pri[i]);
	while(k){
		minn=1;
		for(int i=2; i<=cnt; ++i)
			if(q[i].front()<q[minn].front()) minn=i;
		u=q[minn].front(); q[minn].pop();
		if(--k==0) { printf("%lld\n", u); return 0; }
		for(int i=1; i<=cnt&&pri[i]*u<MAXN; ++i){
			q[i].push(pri[i]*u);
			if(u%pri[i]==0) break;
		}
	}
	return 0;
}

B. Six

本场比赛最毒瘤的题。。。

巨佬 \(szs\) :大家应该都能看出来,这是一个简单的 \(dp\) 。
。。。。
考虑设计状态,显然每个数可以被看作是一个由若干质数组成的集合,既然题中已经告诉了我们每个数最多有 \(6\) 个质因子,因此可以考虑状压。。。
设质因子的状态为 \(S\) 。
若新加入一个数,考虑目前是什么情况它才可以插入。。。
发现当且仅当不存在一个数对,使得当前数与这两个数均含有相同的质因子,因此设是否存在一个同时包含某些质因子的数对的状态为 \(T\) 。。。

转移很麻烦,直接看代码吧。。。

code
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define int long long
#define fi first
#define se second
const int N=1e6+10, M=3e7+10, mod=1e9+7;
inline ll read(){
	int f=1, x=0; char ch=getchar();
	while(!isdigit(ch)) { if(ch=='-') f=-1; ch=getchar(); }
	while(isdigit(ch)) { x=x*10+ch-48; ch=getchar(); }
	return f*x;
}
ll n;
ll stk[N], p[7], cnt[N];
bool vis[M];
int top1, ul1[7][7], f[1<<7], top;
map<pair<int, int > , ll> mp;
int ex[10], top2;
void pre_work(){
	ll ul=n, nn=sqrt(n);
	for(ll i=2; ul!=1&&i<=nn; ++i)
		if(ul%i==0){
			p[++top1]=i;
			while(ul%i==0) ul/=i;
		}
	if(ul!=1) p[++top1]=ul; ul=0;
	for(int i=2; i<=nn; ++i)
		if(n%i==0){
			stk[++top]=i;
			if(i*i!=n) stk[++top]=n/i;
		}
	stk[++top]=n;
	for(int i=1; i<=top; ++i){
		for(int j=1; j<=top1; ++j)
			if(stk[i]%p[j]==0) ul|=1<<(j-1);
		++cnt[ul]; ul=0;
	}
	for(int i=1; i<=top1; ++i) for(int j=i; j<=top1; ++j)
		ul1[i][j]=ul1[j][i]=ul++;
	for(int i=1; i<1<<top1; ++i){
		top2=0;
		for(int j=1; j<=top1; ++j)
			if(i&(1<<(j-1))) ex[++top2]=j;
		for(int j=1; j<=top2; ++j) for(int k=j; k<=top2; ++k)
			f[i]|=(1<<ul1[ex[j]][ex[k]]);
	}
}
ll dfs(pair<int, int > u){
	if(mp[u]) return mp[u]; int ul;
	for(int i=1; i<1<<top1; ++i){
		if(f[i]&u.se) continue;	ul=u.se;
		for(int j=1; j<=top1; ++j){
			if((i&(1<<(j-1)))==0) continue;
			for(int k=1; k<=top1; ++k)
				if(u.fi&(1<<(k-1))) ul|=(1<<ul1[j][k]);
		}
		mp[u]+=((dfs(make_pair(u.fi|i, ul))+1)*cnt[i])%mod;
		mp[u]%=mod;
	}
	return mp[u];
}
signed main(void){
	n=read(); pre_work();
	printf("%lld\n", dfs(make_pair(0, 0)));
	return 0;
}

C. Walker

首先很显然,若确定两个点,则一定可以确定一组解。。。(可以使用高斯消元,也可以直接算出来。。。
若要判断这组解是否合法,则显然可以 \(O(n)\) 判断。。。
若要枚举每一对点对,则显然会 \(T\) ,所以可以考虑随机化优化,因为题中告知,至少有一半的点是正确的,所以一次找到正确答案的概率是 \(\frac{1}{4}\) ,这个概率显然大的可怕,随便随几组数据就能找到。。。(如果 \(RP\) 足够高可以尝试只随一组数据。。。

code
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
const double eps=1e-6;
int n;
double x[N], y[N], x1[N], y10086[N];
double a[10][10], b[10];
inline void gauss(){
	for(int i=1; i<=4; ++i){
		int id=0; double ul;
		for(int j=i; j<=4; ++j)
			if(fabs(a[j][i])>fabs(a[id][i])) id=j;
		ul=a[id][i]; b[id]/=ul;
		for(int j=1; j<=4; ++j) a[id][j]/=ul;
		for(int j=1; j<=4; ++j) swap(a[id][j], a[i][j]); swap(b[id], b[i]);
		for(int j=1; j<=4; ++j){
			if(i==j) continue;
			ul=a[j][i]; b[j]-=ul*b[i];
			for(int k=i; k<=4; ++k)
				a[j][k]-=ul*a[i][k];
		}
	}
}
inline bool check(){
	double xx, yy; int num=0;
	for(int i=1; i<=n; ++i){
		xx=x[i]*b[1]-y[i]*b[2]+b[3]; yy=y[i]*b[1]+x[i]*b[2]+b[4];
		if(fabs(xx-x1[i])<=eps&&fabs(yy-y10086[i])<=eps) ++num;
	}
	return num>=((n+1)>>1);
}
inline void get_ans(){
	double an, scale, dx, dy;
	scale=sqrt(b[1]*b[1]+b[2]*b[2]);
	an=acos(b[1]/scale);
	if(fabs(sin(an)*scale-b[2])>eps) an=-an;
	dx=b[3], dy=b[4];
	printf("%.10lf\n%.10lf\n", an, scale);
	printf("%.10lf %.10lf\n", dx, dy);
}
int main(void){
	scanf("%d", &n); srand(time(0));
	for(int i=1; i<=n; ++i)
		scanf("%lf%lf%lf%lf", &x[i], &y[i], &x1[i], &y10086[i]);
	for(int i=1; i; ++i){
		int a1=rand()%n+1, b1=rand()%n+1;
		if(a1==b1) { --i; continue; }
		a[1][1]=x[a1], a[1][2]=-y[a1], a[1][3]=1, a[1][4]=0; b[1]=x1[a1];
		a[2][1]=y[a1], a[2][2]=x[a1], a[2][3]=0, a[2][4]=1; b[2]=y10086[a1];
		a[3][1]=x[b1], a[3][2]=-y[b1], a[3][3]=1, a[3][4]=0; b[3]=x1[b1];
		a[4][1]=y[b1], a[4][2]=x[b1], a[4][3]=0, a[4][4]=1; b[4]=y10086[b1];
		gauss(); if(check()) { get_ans(); return 0; }
	}
	return 0;
}

标签:10,ch,int,32,ll,long,恩偶,getchar,爱皮
来源: https://www.cnblogs.com/CTcode/p/NOIP_32.html