NOI-Online 2 test200425

NOI-Online 2 test0425

surprise mtf

T1 涂色游戏

题意

你有 \(10^{20}\) 个格子,它们从 \(0\) 开始编号,初始时所有格子都还未染色,现在你按如下规则对它们染色:

  1. 编号是 \(p_1\)倍数的格子(包括 \(0\) 号格子,下同)染成红色。
  2. 编号是 \(p_2\) 倍数的格子染成蓝色。
  3. 编号既是 \(p_1\) 倍数又是 \(p_2\) 倍数的格子,你可以选择染成红色或者蓝色。

其中 \(p_1\)\(p_2\) 是给定的整数,若格子编号是 \(p_1\)\(p_2\) 的倍数则它必须要被染色。在忽略掉所有未染色格子后,你不希望存在 \(k\) 个连续的格子颜色相同,因为你认为这种染色方案是无聊的。现在给定 \(p_1,p_2,k\),你想知道是否有一种染色方案不是无聊的。

得分情况

期望得分:100
实际得分:0-20(luogu民间估计)
改题得分:100

考试想法

真的心态崩了……公式推错了就很棒棒……没啥好讲的,样例跟……一样水。

正解

不妨设 \(p_1<p_2\),且 \(p_1,p_2\) 互质。

则会发现:最坏情况,也就是从 \(kp_2+1\)\((k+1)p_2-1\)这个连续串内塞 \(p_1\) 所对应的颜色。

这样就有 \(\dfrac{p_2-2}{p_1}+1\) 个连续块,将其与 \(k\) 比较即可。

因为可能不互质,所以可以两边除 \(\gcd(p_1,p_2)\) 即可。

T2 子序列问题

题意

给定一个长度为 \(n\) 的正整数序列 \(A_1,A_2,\cdots,A_n\)。定义一个函数 \(f(l,r)\) 表示:序列中下标在 \([l,r]\)范围内的子区间中,不同的整数个数。换句话说,\(f(l,r)\) 就是集合 ${A_l,A_{l+1},\cdots,A_r} $的大小,这里的集合是不可重集,即集合中的元素互不相等。

现在,请你求出\(\sum_{l=1}^n\sum_{r=l}^n (f(l,r))^2\)。由于答案可能很大,请输出答案对 \(10^9 +7\) 取模的结果。

得分情况

期望得分:100
实际得分:70-100(luogu民间估计)
改题得分:100(直接开O2没有改动)

考试想法

正解……可能我太弱了,没算好复杂度,以为线段树可以过……

而且可能也不是线段树的问题,我用的map,用离散化将快的飞起。

我们从前往后递推当前位置 \(i\) 加入了新数 \(a_i\)

对于每次加入了\(a_i\) 我们需要计算

\(tmp_i=\sum_{l=1}^i (f(l,i))^2\),然后就可以直接 \(ans=ans+tmp\) 了。

怎样快速的计算\(tmp\)呢。

不妨设 \(b_j\)\(f(j,i)\)

那么每次枚举到的新的 \(b_i\)\(1\)

对于\(b_j(j\in[1,i-1])\) ,设s为最后一次出现 \(a_i\) 的位置(离散化和map皆可)。

\[b_j=\begin{cases} b_j+1 \quad j\in{[s+1,i-1]}\\ b_j\quad\quad\ \ \ j\in{[1,s]} \end{cases}\\ \]

这个可以用 线段树 树状数组维护。

此时我们需要计算的 \(tmp_i= \sum_{j=1}^ib_j^2\)

此时我们已经有了\(tmp_{i-1}\) ,那么我们的问题变为了怎样快速的转换 \(tmp_i\)

此时,\(b_j,j\in[s+1,i-1]\) 已经变为了\(b_j+1\),此时给 \(tmp\) 的贡献是多少呢?

我们易知这个小学算式

\[(n +1)^2=n^2+2n+1\\(n+1)^2-n^2=2n+1 \]

每个 \(b_j,j\in[s+1,i-1]\)\(tmp\) 贡献了 \(2b_i+1\)

我们可以直接用线段树 树状数组计算出\(sss=\sum_{j=s+1}^{i-1} 2b_j+1\)

那么 \(tmp_i=tmp_{i-1}+sss+b_i^2\) ,这里前面讲到了 \(b_i=1\)

然后就可以愉快的 \(ans=ans+tmp_i\)了。

这里附上一下线段树的假代码,开 O2 在Luogu 上可过……但是我肯定凉凉了……

#include<bits/stdc++.h>
using namespace std;

#define int long long
#define Int signed

const int maxn=1e6+10;
const int mod=1e9+7;

map<int,int>ma;

int n;

struct sgt_tree{
	int a[maxn<<2],f[maxn<<2];
	
	inline void push_up(int x){
		a[x]=a[x<<1]+a[x<<1|1];
		return;
	}
	
	inline void push_down(int x,int l,int r){
		if(f[x]){
			int mid=(l+r)>>1;
			f[x<<1]+=f[x];
			f[x<<1|1]+=f[x];
			a[x<<1]+=(mid-l+1)*f[x];
			a[x<<1|1]+=(r-mid)*f[x];
			f[x]=0;
		}
		return;
	}

	int sum(int x,int l,int r,int L,int R){
		if(L>R)
			return 0;
		int s=0;
		if(L<=l && r<=R)
			s+=a[x];
		else{
			push_down(x,l,r);
			int mid=(l+r)>>1;
			if(L<=mid)
				s+=sum(x<<1,l,mid,L,R);
			if(mid<R)
				s+=sum(x<<1|1,mid+1,r,L,R);
		}
		return s;
	}

	void add(int x,int l,int r,int L,int R){
		int mid=(l+r)>>1;
		if(L<=l && r<=R){
			a[x]+=r-l+1;
			f[x]++;
		}
		else{
			push_down(x,l,r);
			if(L<=mid)
				add(x<<1,l,mid,L,R);
			if(mid<R)
				add(x<<1|1,mid+1,r,L,R);
			push_up(x);
		}
		return;
	}
}sgt;

inline int read(){
	int x=0,c=getchar();
	while(!isdigit(c))
		c=getchar();
	while(isdigit(c)){
		x=(x<<3)+(x<<1)+c-'0';
		c=getchar();
	}
	return x;
}

int ans,tmp;

Int main(){
#ifdef ZTZ_CPP
	freopen("sequence.in","r",stdin);
	freopen("sequence.out","w",stdout);
#endif
	int x;
	scanf("%lld",&n);
	for(register int i=1;i<=n;i++){
		x=read();
		int s=ma[x];
		ma[x]=i;
		//tmp=(tmp+i-1-s+sgt.sum(1,1,n,s+1,i-1)*2+1)%mod;
		tmp=(tmp+i-s+sgt.sum(1,1,n,s+1,i-1)*2%mod)%mod;
		sgt.add(1,1,n,s+1,i);
		ans=(ans+tmp)%mod;
	}
	printf("%lld\n",ans);
	return 0;
}

正解

用树状数组……

T3 游戏

题意

小 A 和小 B 正在玩一个游戏:有一棵包含 \(n=2m\) 个点的有根树(点从 \(1\sim n\)编号),它的根是 \(1\) 号点,初始时两人各拥有 \(m\) 个点。游戏的每个回合两人都需要选出一个自己拥有且之前未被选过的点,若对手的点在自己的点的子树内,则该回合自己获胜;若自己的点在对方的点的子树内,该回合自己失败;其他情况视为平局。游戏共进行 \(m\) 回合。

作为旁观者的你只想知道,在他们随机选点的情况下,第一次非平局回合出现时的回合数的期望值。
为了计算这个期望,你决定对于 \(k=0,1,2,\cdots,n\)计算出第一次非平局回合出现在第 \(k\) 个回合的情况数。两种情况不同当且仅当存在一个小 A 拥有的点 \(x\),小 B 在 \(x\) 被小 A 选择的那个回合所选择的点不同。

由于情况总数可能很大,你只需要输出答案对 \(998244353\) 取模后的结果。

\(n \le 5000\)

得分情况

实际得分:没写
改题得分:

正解

(借用韬哥的sol搞一波)

大概?是个玄学数学公式+树上DP吧

树上DP可能想的到,不过真的不知道从何下手就没动了……还是太菜了……

考试总结

可能还是考试的时候没有多想

第一题看到旁边人推出来了于是也急了

发现自己的公式可以过样例就直接交了一手也没验证……

然后T2想当然的以为map跑得快……

一开始想过要改成离散化的

但是由于懒了还是没去改……然后得分就这么看脸了…………

T3可能也就没啥心情想做了

没看出暴力怎么打于是就放弃了……

下次考试还是要分配好时间

简单的题目多验证几下

然后还要多考虑优化代码,鬼晓得评测机会出什么玄学事故……

posted @ 2020-04-25 15:19  ztz_cpp  阅读(246)  评论(0编辑  收藏  举报