• 某考试T2 frog


    题目背景

    题目描述

    数轴上有 n 只青蛙,分别编号为 1 到 n。青蛙 i 的初始位置的坐标为 xi。 它们准备进行如下形式的移动:每轮包括 m 次跳跃,第 i 次跳跃由青蛙 ai(1 < ai < n) 执行。青蛙 ai 会从青蛙 ai − 1 和青蛙 ai + 1 中等概率地选一 只,假设选出的青蛙所在的位置为 p,那么青蛙 ai 会跳到它当前位置关于 p 的 对称点。 青蛙们会连续进行 k 轮这样的移动。请你对每只青蛙,求出它最终坐标的 期望值。

    输入输出格式

    输入格式:

    第一行为一个整数 n。 接下来一行 n 个整数 x1, x2, ..., xn。 接下来一行为两个整数 m, k。 接下来一行为 m 个整数 a1, a2, ..., am。

    输出格式:

    输出共 n 行,第 i 的数表示青蛙 i 的最终坐标的期望值,四舍五入到整数 后输出。

    输入输出样例

    输入样例#1: 
    5
    -1 3 5 0 2
    3 2
    2 3 4
    
    输出样例#1: 
    -1
    -6
    -4
    0
    2
    

    说明

    对于 20% 的数据,保证 3 ≤ n ≤ 20, 1 ≤ m ≤ 20, k = 1。 对于 40% 的数据,保证 3 ≤ n ≤ 1000, 1 ≤ m, k ≤ 1000。 对于 70% 的数据,保证 3 ≤ n ≤ 1000, 1 ≤ m ≤ 1000, 1 ≤ k ≤ 1018。 对于 100% 的数据,保证 3 ≤ n ≤ 105 , 1 ≤ m ≤ 105, 1 ≤ k ≤ 1018,|xi| ≤ 109, 1 < ai < n。

    考试的时候xjb找了一下循环节,写hash还写挂了才得了60分2333。

    题解见代码注释》》》

    发现一个神规律之后就是一个O(N)题了

    /*
        首先推式子可以得到p[i]跳后的坐标
    	f[p[i]]=(2*f[p[i]-1]-f[p[i]])/2+(2*f[p[i]+1]-f[p[i]])/2 
    	化简之后对原位置差分,可以发现跳一次就是交换一下自己和后面
    	位置的差分,于是对于每一次跳我们就处理出一个置换,然后
    	答案就可以从置换的K次幂之后对应的差分上计算了。 
    */ 
    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #define ll long long
    #define maxn 100005
    using namespace std;
    ll pos[maxn],k,ans[maxn];
    int n,m,a[maxn],to[maxn];
    int p[maxn],now,circle[maxn];
    bool v[maxn];
    
    inline int add(int x,const int ha){
    	x++;
    	if(x>=ha) return x-ha;
    	else return x;
    }
    
    inline void work(int x){
    	int len=0;
    	while(!v[x]){
    		circle[++len]=x;
    		v[x]=1,x=to[x];
    	}
    	
    	int y=k%len;
    	
    	for(int i=1;i<=len;i++,y=add(y,len)){
    		to[circle[i]]=circle[y+1];
    	}
    } 
    
    inline void solve(){
    	for(int i=1;i<=n;i++) if(!v[i]) work(i);
    }
    
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++) scanf("%lld",pos+i),p[i]=i;
    	//做一次差分 
    	for(int i=n;i;i--) pos[i]-=pos[i-1];
    	
    	scanf("%d%lld",&m,&k);
    	for(int i=1;i<=m;i++){
    		scanf("%d",&now);
    		//now这个青蛙跳一次相当于交换一下它和它后面一个位置的差分 
    		swap(p[now],p[now+1]);	
    	}
    	for(int i=1;i<=n;i++){
    		//我们已经知道了i位置在一次操作之后的差分是p[i]位置的 
    		//也就是p[i]位置的差分在一次差分之后移到了i位置 
    		//所以我们得到的是一个置换的逆 
    		//于是我们需要把边反向从而求出置换 
    		to[p[i]]=i;
    	}
    
    	//找置换 
    	solve();
    
    	for(int i=1;i<=n;i++) ans[to[i]]=pos[i];
    	for(int i=1;i<=n;i++){
    		ans[i]+=ans[i-1];
    		printf("%lld
    ",ans[i]);
    	}
    	
    	return 0;
    } 
    

      

  • 相关阅读:
    设计模式_2_简单工厂、工厂方法、抽象工厂比较
    SQL模拟padding函数
    MySqlHelper c#访问MySql的工具类
    常见数据库设计(1)——字典数据
    常见数据库设计(2)——历史数据问题之单记录变更
    设计模式_1_单例模式
    代码调用存储过程超时,SQL Server Management Studio里运行很快 (改进)
    转:Rowid和Rownum区别
    Oracle数据库中system和sys的区别
    转:Python之全局变量
  • 原文地址:https://www.cnblogs.com/JYYHH/p/8474637.html
Copyright © 2020-2023  润新知