2018.11.1模拟赛

T1

考虑一个 n×nn\times nn×n 的矩阵 AAA,初始所有元素均为 000。 执行 q 次如下形式的操作:给定 444 个整数 r,c,l,sr,c,l,sr,c,l,s,对于每个满足 x∈[r,r+l),y∈[c,x−r+c]x ∈ [r,r+l), y ∈ [c,x−r+c]x[r,r+l),y[c,xr+c] 的元素 (x,y)(x,y)(x,y),将权值增加 sss。也就是,给一个左上顶点为 (r,c)(r,c)(r,c)、直角边长为 lll 的下三角区域加 上 sss。 输出最终矩阵的元素异或和。

保证 n∈[1,103],q∈[0,3×105],r,c,l∈[1,n],s∈[1,109]n ∈ [1,10^3],q ∈ [0,3\times 10^5],r,c,l ∈ [1,n],s ∈ [1,10^9]n[1,103]q[0,3×105]r,c,l[1,n]s[1,109]

挺简单的,就是二维前缀和,O(1)O(1)O(1)修改,n2n^2n2算答案

放上考场ACACAC代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define maxn 3005
#define LL long long
using namespace std;
int n,q;
LL row[maxn][maxn],line[maxn][maxn],a[maxn][maxn],ans;

inline int rd(){
	int x=0,f=1;char c=' ';
	while(c<'0' || c>'9') f=c=='-'?-1:1,c=getchar();
	while(c<='9' && c>='0') x=x*10+c-'0',c=getchar();
	return x*f;
}

int main(){
	freopen("u.in","r",stdin);
	freopen("u.out","w",stdout);
	n=rd(); q=rd();
	while(q--){
		int x=rd(),y=rd(),l=rd(),s=rd();
		a[x][y]+=s; a[x+l][y]-=s;
		line[x][y+1]-=s; line[x+l][y+l+1]+=s;
	}
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			line[i][j]+=line[i-1][j-1],a[i][j]+=a[i-1][j];
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			a[i][j]+=a[i][j-1]+line[i][j],ans^=a[i][j];
	printf("%lld\n",ans);
}

T2

nnn 个球排成一行,每个球的颜色为黑或白。 执行 kkk 次操作,第 i(1≤i≤k)i(1 ≤ i ≤ k)i(1ik) 次操作形式如下:

• 从 [1,n−i+1][1,n−i + 1][1,ni+1] 中,等概率随机选择一个整数 xxx

• 移除从左往右数的第 xxx 个球,或从右往左数的第 xxx 个球(也就是从左往右数的第 n−i+2−xn−i+2−xni+2x 个)。之后,所有右侧的球的编号减 111
给定每个球的颜色信息,希望最大化移除的白球数量。 输出在最优策略下,期望的移除白球数量。误差在 10−610^{-6}106 范围内,即算正确。
n≤30n\le 30n30,时限3000ms3000ms3000ms

solution:

就是一道期望的题,期望部分很简单,但是细节很多很复杂,可以用记搜实现,但是这是一道卡常神题,考场无人ACACAC,凭着优秀的常数拿到了969696分,但其实考场手懒都开的mapmapmap,前面242424位可以开数组,这样就可以拿满分了(什么zzzzzz

先放上考场969696分代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<map>
#define maxn 35
#define LL long long
using namespace std;
int n,m,a[maxn];
char s[maxn];
double ans;
const double eps=1e-10;
LL bin;
map< pair<LL,int>,double > mp;

inline void work(int x){
	x=n-x+1;
	LL y=bin&((1LL<<x)-1);
	bin=(bin^y)|((y&((1LL<<(x-1))-1))<<1);
}

inline int calc(LL x){
	int cnt=0;
	while(x){
		if(x&1) cnt++;
		x>>=1LL;
	} return cnt;
}

inline double max(double x,double y){return x>y?x:y;}

double dfs(int now){
	if(now==m+1 || bin==0) return 0.0;
	if(mp[make_pair(bin,now)]>eps) return mp[make_pair(bin,now)];
	double res=0.0,qwq; LL tmp=bin; int x;
	for(int i=1;i<=n-now+1;i++){
		x=(bin&(1LL<<(n-i)))?1:0; work(i);
		qwq=(x+dfs(now+1))*1.0/(n-now+1);
		bin=tmp;
		x=(bin&(1LL<<(now-2+i)))?1:0; work(n-now+2-i);
		qwq=max(qwq,(x+dfs(now+1))*1.0/(n-now+1));
		bin=tmp;
		res+=qwq;
	}
	return mp[make_pair(bin,now)]=res;
}

int main(){
//	freopen("in.txt","r",stdin);
//	freopen("out2.txt","w",stdout);
//	freopen("v.in","r",stdin);
//	freopen("v.out","w",stdout);
	scanf("%d%d%s",&n,&m,s+1);
	int ccnt=0;
	for(int i=1;i<=n;i++)
		a[i]=(s[i]=='W')?1:0,bin=(bin<<1LL)|a[i],ccnt+=a[i];
	if(m==n) return printf("%.10lf\n",(double)ccnt),0;
	printf("%.10lf\n",dfs(1));
	return 0;
}

然后是改完的(其实就差那么一步啊

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<map>
#include<unordered_map>
#define maxn 35
#define LL long long
using namespace std;
int n,m,a[maxn];
char s[maxn];
double ans,f[(1<<24)+5];
const double eps=1e-10;
LL bin,num;
unordered_map< LL,double > mp[31];

inline void work(int x,int len){
	x=len-x+1;
	int y=bin&((1<<(x-1))-1);
	bin=((bin>>x)<<(x-1))|y;
}

inline int calc(int len){
	int cnt=0;
	for(int i=1;i<=len;i++)
		cnt+=a[i];
	return cnt;
}

double dfs(int now){
	if(now==m+1 || bin==0) return 0.0;
	double res=0.0; LL tmp=bin;
	int len=n-now+1;
	if(len<24 && f[1<<len|bin]!=-1) return f[1<<len|bin];
	if(mp[now].count(bin)) return mp[now][bin];
	for(int i=1;i<=(len+1)/2;i++){
		double qwq=0.0;
		int x=(bin>>(len-i))&1; work(i,len);
		if((len&1) && i==(len+1)/2)
			qwq=(x+dfs(now+1))*1.0/len;
		else qwq=(x+dfs(now+1))*2.0/len;
		bin=tmp;
		x=(bin>>(len-(n-now+2-i)))&1; work(n-now+2-i,len);
		if((len&1) && i==(len+1)/2)  
			qwq=max(qwq,(x+dfs(now+1))*1.0/len);
		else qwq=max(qwq,(x+dfs(now+1))*2.0/len);
		bin=tmp;
		res+=qwq;
	}
	if(len<24) return f[1<<len|bin]=res;
	else return mp[now][bin]=res;
}

int main(){
	freopen("v.in","r",stdin);
	freopen("v.out","w",stdout);
	scanf("%d%d%s",&n,&m,s+1); int ccnt=0;
	for(int i=1;i<=n;i++)
		a[i]=(s[i]=='W')?1:0,bin=(bin<<1LL)|a[i],ccnt+=a[i];
	if(m==n) return printf("%.10lf\n",(double)ccnt),0;
	for(int i=1;i<(1<<24);i++) f[i]=-1;
	printf("%.10lf\n",dfs(1));
	return 0;
}

还听ghostcaighostcaighostcai的用了c++11c++11c++11unordered_mapunordered\_mapunordered_map但好像没什么卵用
顺便说大力卡常以后极限数据只跑了1.8ms1.8ms1.8msqwqqwqqwq

T3

树形dpdpdp,完了有时间改吧···

总分100+96+5(如果不CE)=201100+96+5(如果不CE)=201100+96+5(CE)=201,好像可以稍微拯救一下我跌下去的均分???

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值