zoukankan      html  css  js  c++  java
  • 【luoguP5550】Chino的数列

    题目背景

    没有背景

    我写不出来了qwq

    题目描述

    Chino给定了nn个数a_1...a_na1...an,给定常数s,m,她会轮流对这nn个数做k组操作,每组操作包含以下几步:

    1.swap(as,am)(交换a_s,a_m)

    2.2n个数都向前平移一位(第11个移动到第n个位置上)

    Chino想知道,k组操作后,这nn个数分别是多少?

    Orz yky,dyh,wjk,jjy,cxr,gsy,cpy,zcy,tyz,yy,hz,zhr,yg

    输入格式

    第一行,四个数,n,s,m,k

    接下来一行n个数,分别代表a_1,a_2...a_na1,a2...an

    输出格式

    输出一行,n个数,分别代表a_1,a_2...a_na1,a2...an

    输入输出样例

    输入 #1
    4 1 2 3
    1 2 3 4
    输出 #1
    1 2 3 4

    说明/提示

    所有数字均在long long以内

    思路:

      矩阵加速递推,构造两个矩阵,一个存交换操作,一个存位移操作。

      假如交换1和2:

          0 1 0 0

          1 0 0 0

          0 0 0 1

          0 0 0 1

      位移操作,所有往前移一位,

             0 1 0 0

          0 0 1 0

          0 0 0 1

          1 0 0 0    

    矩阵快速幂求解K次方,即操作次数:

    jz ksm(jz a,int b)
    {
    	jz anss;
    	memset(anss.c,0,sizeof(anss.c));
    	for(int i=1;i<=n;i++) anss.c[i][i]=1;
    	for(;b;b>>=1,a=a*a)
    	{
    		if(b&1)anss=a*anss;
    //		a=a*a;当时出错了,因为前面已经计算
    	}
    	return anss;
    }
    

    重载乘号:

    struct jz{
    	int c[100][100];
    }f,base,l1,l2;
    int n,m,s,k;
    jz operator * (const jz &a,const jz &b)
    {
    	jz lin;
    	for(int i=1;i<=80;i++)
    		for(int j=1;j<=80;j++)
    		{
    			lin.c[i][j]=0;
    			for(int k=1;k<=80;k++)
    			{
    				lin.c[i][j]+=(a.c[k][j] * b.c[i][k]);
    			}
    		}
    	return lin;
    }

     代码:

    #include<cstdio>
    #include<cstdlib>
    #include<iostream>
    #include<cmath>
    #include<cstring>
    #define int long long
    using namespace std;
    struct jz{
    	int c[100][100];
    }f,base,l1,l2;
    int n,m,s,k;
    jz operator * (const jz &a,const jz &b)
    {
    	jz lin;
    	for(int i=1;i<=80;i++)
    		for(int j=1;j<=80;j++)
    		{
    			lin.c[i][j]=0;
    			for(int k=1;k<=80;k++)
    			{
    				lin.c[i][j]+=(a.c[k][j] * b.c[i][k]);
    			}
    		}
    	return lin;
    }
    void dy(jz x)//调试用的,可以忽略
    {
        for(int i=1;i<=n;++i)
        {
            for(int j=1;j<=n;++j)
            cout<<x.c[i][j]<<" ";
            cout<<endl;
        }
    }
    jz ksm(jz a,int b)
    {
    	jz anss;
    	memset(anss.c,0,sizeof(anss.c));
    	for(int i=1;i<=n;i++) anss.c[i][i]=1;
    	for(;b;b>>=1,a=a*a)
    	{
    		if(b&1)anss=a*anss;
    //		a=a*a;
    	}
    	return anss;
    }
    signed main()
    {
    	scanf("%lld%lld%lld%lld",&n,&s,&m,&k);
    	for(int i=1;i<=n;i++) scanf("%lld",&f.c[i][1]);
    	for(int i=1;i<=n;i++) if(i!=s&&i!=m)l1.c[i][i]=1;
    	l1.c[s][m]=l1.c[m][s]=1;
    	for(int i=1;i<=n-1;i++)l2.c[i][i+1]=1;
    	l2.c[n][1]=1;
    	base=l1*l2;
    	base=ksm(base,k);
    	f=f*base;
    	for(int i=1;i<=n;i++)printf("%lld ",f.c[i][1]);
    	cout<<endl;
    	dy(l1);
    	cout<<endl;
    	dy(l2);
    	return 0;
    }
    

      

    感谢wlj_dy 的帮助

  • 相关阅读:
    Mac OS使用brew安装memcached
    Mac OS使用brew安装memcached
    Mac OS使用brew安装memcached
    JAVA学习之路 (五) 类
    JAVA学习之路 (五) 类
    JAVA学习之路 (五) 类
    JAVA学习之路 (五) 类
    常用的CSS小技巧
    常用的CSS小技巧
    常用的CSS小技巧
  • 原文地址:https://www.cnblogs.com/yelir/p/11525619.html
Copyright © 2011-2022 走看看