• 2020.11.25 考试题解


    T2

    【题目描述】
    
    有一圈数,其数目为n个,定义一次操作为每个数变为原数圈中的自己与相邻的两个数这三个数的异或和,给出原数组和操作次数,请算出最后的结果数组。
    
    
    【输入数据】
    
    输入第一行包含两个正整数n和k,分别表示数组数目和操作次数。第二行$n$个整数。
    
    
    【输出数据】
    
    仅包含一行n个整数。
    

    样例输入:

    3 1
    1 2 3
    

    样例输出:

    0 0 0
    

    数据范围:

    对于(30%)的数据,(n imes kleq 10^8)

    对于(100%)的数据,(1leq nleq 10^5,1leq kleq 10^9)

    分析:

    对于(a_i),进行一次操作后,会变为(a_{i-1})$a_i$(a_{i+1})

    两次操作后,会变为(a_{i-2})$a_i$(a_{i+2})

    三次操作后,会变为(a_{i-3})$a_{i-2}$(a_i)$a_{i+2}$(a_{i+3})

    四次操作后,会变为(a_{i-4})$a_i$(a_{i+4})

    我们发现当操作次数为(2^k)时,(a_i)会变为(a_{i-{2^k}})$a_i$(a_{i+{2^k}})

    由此,我们可以将(k)次操作进行二进制分解,一定可以完全分解,将(k)降为(log_k),每次(O(n))暴力操作,时间复杂度为(O(n imes log_k))

    (Code:)

    #include<bits/stdc++.h>
    using namespace std;
    #define il inline
    #define vocaloid(v) (v>='0'&&v<='9')
    template <typename T>
    il void read(T &x)
    {
    	x=0;char v=getchar();
    	while(!vocaloid(v)) v=getchar();
    	while(vocaloid(v)) {x=(x<<1)+(x<<3)+v-'0';v=getchar();}
    }
    template <typename T>
    il void write(T x)
    {
    	if(x>9) write(x/10);
    	putchar(x%10+'0');
    }
    int n,k,a[100039],b[10039];
    int main()
    {
    	freopen("xor.in","r",stdin);
    	freopen("xor.out","w",stdout);
    	read(n),read(k);
    	for(int i=1;i<=n;i++) read(a[i]);
    	for(int pos=1;k;pos<<=1,k>>=1)
    	{
    		if(k&1)
    		{
    			for(int i=1;i<=n;i++) b[i]=a[i];
    			for(int l=((-pos%n)+n)%n+1,r=(pos%n)+1,i=1;i<=n;i++)
    			{
    				a[i]^=b[l++]^b[r++];
    				if(l>n) l=1;
    				if(r>n) r=1;
    			}
    		}
    	}
    	for(int i=1;i<=n;i++) write(a[i]),putchar(' ');
    	return 0;
    }
    
  • 相关阅读:
    『Python』进程同步
    『Python』多进程
    『GoLang』协程与通道
    『GoLang』错误处理
    『码农翻身』语言的学习
    『GoLang』fmt包的使用
    异或运算符(^)、与运算符(&)、或运算符(|)、反运算符(~)、右移运算符(>>)、无符号右移运算符(>>>)
    HTML DOM focus() 方法
    JavaScript中的indexOf使用方法
    HTML 5 中的textarea标签
  • 原文地址:https://www.cnblogs.com/MIKU5201314/p/14086739.html
Copyright © 2020-2023  润新知