zoukankan      html  css  js  c++  java
  • 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}^nsum_{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(jin[1,i-1])) ,设s为最后一次出现 (a_i) 的位置(离散化和map皆可)。

    [b_j=egin{cases} b_j+1 quad jin{[s+1,i-1]}\ b_jquadquad jin{[1,s]} end{cases}\ ]

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

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

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

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

    我们易知这个小学算式

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

    每个 (b_j,jin[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
    ",ans);
    	return 0;
    }
    

    正解

    用树状数组……

    T3 游戏

    题意

    小 A 和小 B 正在玩一个游戏:有一棵包含 (n=2m) 个点的有根树(点从 (1sim 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可能也就没啥心情想做了

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

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

    简单的题目多验证几下

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

  • 相关阅读:
    python,生产环境安装
    neo4j 图数据库
    RNN系列
    机器学习关于AUC的理解整理
    fensorflow 安装报错 DEPENDENCY ERROR
    dubbo Failed to check the status of the service com.user.service.UserService. No provider available for the service
    使用hbase遇到的问题
    MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk
    gradle 安装
    jenkins 安装遇到的坑
  • 原文地址:https://www.cnblogs.com/ztz-cpp/p/12773192.html
Copyright © 2011-2022 走看看