zoukankan      html  css  js  c++  java
  • 【XSY3126】异或II 数学

    题目描述

      给你一个序列 (a_0,a_1,ldots,a_{n-1})。你要进行 (t) 次操作,每次操作是把序列 (x) 变为序列 (y),满足 (y_i=oplus_{j=0}^{k-1}x_{(i+j)mod n})(oplus) 表示异或。

      求 (t) 次操作后的序列。

      (1leq kleq nleq 500000,tleq {10}^{18})

    题解

      设 (f_{i,j}) 为原序列进行 (i) 次操作后是哪些数的异或和。

      设 (F_i(x)=sum_{j=0}^{n-1}f_{i,j}x^j)

      那么 (F_i(x)=(1+x+cdots x^{k-1})F_{i-1}(x))

      注意到模 (2) 意义下的多项式的平方是很好求的,只需要把所有 (x^i) 改成 (x^{2i}) 就好了。因为其他项的系数都是 (2)的倍数。

      所以 (F_{2^t}(x)=1+x^{2^t}+cdots+x^{(k-1)2^t}),那么乘上 (F_{2^t}(x)) 就是

    [y_i=oplus_{j=0}^{k-1}x_{(i+j imes 2^t)mod n} ]

      然后暴力算就可以了。

      时间复杂度:(O(nlog t))

    代码

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cstdlib>
    #include<ctime>
    #include<utility>
    #include<functional>
    #include<cmath>
    #include<vector>
    //using namespace std;
    using std::min;
    using std::max;
    using std::swap;
    using std::sort;
    using std::reverse;
    using std::random_shuffle;
    using std::lower_bound;
    using std::upper_bound;
    using std::unique;
    typedef long long ll;
    typedef unsigned long long ull;
    typedef double db;
    typedef std::pair<int,int> pii;
    typedef std::pair<ll,ll> pll;
    void open(const char *s){
    #ifndef ONLINE_JUDGE
    	char str[100];sprintf(str,"%s.in",s);freopen(str,"r",stdin);sprintf(str,"%s.out",s);freopen(str,"w",stdout);
    #endif
    }
    int rd(){int s=0,c,b=0;while(((c=getchar())<'0'||c>'9')&&c!='-');if(c=='-'){c=getchar();b=1;}do{s=s*10+c-'0';}while((c=getchar())>='0'&&c<='9');return b?-s:s;}
    void put(int x){if(!x){putchar('0');return;}static int c[20];int t=0;while(x){c[++t]=x%10;x/=10;}while(t)putchar(c[t--]+'0');}
    int upmin(int &a,int b){if(b<a){a=b;return 1;}return 0;}
    int upmax(int &a,int b){if(b>a){a=b;return 1;}return 0;}
    const int N=500010;
    bool c[N];
    int a[N];
    int b[N];
    int d[N];
    int n,k;
    ll m;
    int gcd(int a,int b)
    {
    	return b?gcd(b,a%b):a;
    }
    int cnt;
    int plus(int a,int b)
    {
    	a+=b;
    	return a>=n?a-n:a;
    }
    int minus(int a,int b)
    {
    	a-=b;
    	return a<0?a+n:a;
    }
    void gao(int t)
    {
    	if(!t)
    		return;
    	memset(c,0,sizeof c);
    	memcpy(b,a,sizeof a);
    	int kk=k%(2*n/gcd(t,n));
    	for(int i=0;i<n;i++)
    		if(!c[i])
    		{
    			cnt=0;
    			for(int j=i;!c[j];j=plus(j,t))
    				d[++cnt]=j,c[j]=1;
    			int s=0;
    			int now=d[cnt];
    			for(int j=0;j<kk;j++,now=plus(now,t))
    				s^=b[now];
    			a[d[cnt]]=s;
    			for(int j=cnt-1;j>=1;j--)
    			{
    				now=minus(now,t);
    				s^=b[d[j]];
    				s^=b[now];
    				a[d[j]]=s;
    			}
    		}
    }
    int main()
    {
    	open("b");
    	scanf("%d%d%lld",&n,&k,&m);
    	for(int i=0;i<n;i++)
    		a[i]=rd();
    	for(ll i=1;i<=m;i<<=1)
    		if(m&i)
    			gao(i%n);
    	for(int i=0;i<n;i++)
    		printf("%d ",a[i]);
    	return 0;
    }
    
  • 相关阅读:
    数据仓库
    HiveSQL 数据定义语言(DDL)
    HiveSQL 数据操控、查询语言(DML、DQL)
    【ASP.NET Core】Blazor+MiniAPI完成文件下载
    MySQL的WAL(WriteAhead Logging)机制
    MySQL系列 | 索引数据结构大全
    眼见为实,看看MySQL中的隐藏列
    mysql的默认隔离级别:可重复读(Repeatable Read)
    缓存淘汰算法LRU算法
    Android设计模式系列(12)SDK源码之生成器模式(建造者模式)
  • 原文地址:https://www.cnblogs.com/ywwyww/p/9250649.html
Copyright © 2011-2022 走看看