Alice’s Sequence II
Problem Description
Alice loves play with the math, though she always doesn’t know how to solve her own problems.
Alice writes down a sequence(called a) of N integers on the blackboard, indexing from 1 to N, then she wants to do some operations on this sequence. She defines four types of operations.
- remove i: a i = 0 a_i=0 ai=0
- double i: a i = 2 ∗ a i a_i=2* a_i ai=2∗ai
- add i j: a i = a i + a j a_i= a_i + a_j ai=ai+aj
- swap i j: swap the number of a i a_i ai , a j a_j aj
- invert i j: invert the sequence from index i i i to index j j j ( i ≤ j ) (i ≤ j) (i≤j), for example, a = 1 , 2 , 3 , 4 , 5 , 6 a = 1,2,3,4,5,6 a=1,2,3,4,5,6, after operation “invert 1 6”, a will turn into sequence of 6 , 5 , 4 , 3 , 2 , 1 6,5,4,3,2,1 6,5,4,3,2,1
- transform c i d j: a i = c ∗ a i + d ∗ a j a_i = c*a_i + d*a_j ai=c∗ai+d∗aj and a j = 0 a_j = 0 aj=0
Alice will give out a operation sequence S with M operations, naming from 1 to M, you need to make P steps on this operation set S. You must make the operation S one by one, and if you reach the Mth operation, you should make the operation on the 1st operation in your next step. For example, if the size of S is 5, and we need to make 8 steps, we make operation S1, S2, …, S5, S1, S2 and S3. Alice wonders what would happen after all of P steps.
For the “double”, “add” and “transform” operations would lead the value of sequence become too large to express, so, you just need to output the sequence by mod 10000007 to each element.
Input
There are multiple cases. In each case, it contains an integer N ( 1 ≤ N ≤ 25 1≤ N ≤25 1≤N≤25) in the first line. The following line contains N integers representing the initial value of sequence of a. All of the initial value of sequence of a is a non-negative number and less than 100.
Then it comes an integer M ( 1 ≤ M ≤ 10 1 ≤ M ≤ 10 1≤M≤10) in one line, th following M lines contain M operations on each line. The operation is claimed above. The format is “name_of_operation parameters”, name_of_operation can be “remove”, “double”, “add”, “swap”, “invert”, “transform”. And the parameters is a list of parameter which has different length according to the description above. Specially, the integer c and the integer d are non-negative and less than 100.
Finally, the input contains an integer P ( 1 ≤ P ≤ 1 0 9 1≤ P ≤ 10^9 1≤P≤109) in one line, which means the total steps you need to make.
Output
For each case, you should output the result of sequence a after P steps.
Sample Input
10
1 2 3 4 5 6 7 8 9 10
6
transform 1 2 3 4
remove 1
swap 2 3
add 2 9
double 9
invert 2 6
8
Sample Output
0 6 5 0 14 12 7 8 18 10
题意
有n个数字的序列,可以执行以下指令:
- remove i: a i = 0 a_i=0 ai=0
- double i: a i = 2 ∗ a i a_i=2* a_i ai=2∗ai
- add i j: a i = a i + a j a_i= a_i + a_j ai=ai+aj
- swap i j: 交换 a i a_i ai , a j a_j aj
- invert i j:将 [ i , j ] [i,j] [i,j]的数逆序
- transform c i d j: a i = c ∗ a i + d ∗ a j a_i = c*a_i + d*a_j ai=c∗ai+d∗aj and a j = 0 a_j = 0 aj=0
一轮共有m条指令,共需要执行p条,一轮m条指令执行完成后,在从第一条指令开始执行。求最后的序列。
题解:
因为p较大,n较小,且指令都可用矩阵乘法来实现。将一轮的操作,利用矩阵乘法变为一个矩阵,求该矩阵的p/m次幂。再按顺序执行p%m条指令即可。
注意
i
=
=
j
i == j
i==j的情况,以及最后一个操作,需要最后将
a
[
j
]
[
j
]
a[j][j]
a[j][j]赋为0。
#include<stdio.h>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<map>
#include<vector>
#include<queue>
#include<iterator>
#define dbg(x) cout<<#x<<" = "<<x<<endl;
#define INF 0x3f3f3f3f
#define eps 1e-6
using namespace std;
typedef long long LL;
typedef pair<int, int> P;
const int maxn = 12;
const int mod = 10000007;
struct matrix{
LL a[32][32];
}s, t, p[maxn];
int n;
char str[40];
matrix Mul(matrix a, matrix b);
matrix Pow(matrix a, int b);
int main()
{
int m, i, j, k, c, d, q;
while(scanf("%d", &n)!=EOF)
{
memset(s.a, 0, sizeof(s.a));
for(i=1;i<=n;i++)
scanf("%lld", &s.a[1][i]);
scanf("%d", &m);
for(i=0;i<m;i++){
scanf(" %s", str);
memset(p[i].a, 0, sizeof(p[i].a));
for(j=0;j<=n;j++)
p[i].a[j][j] = 1;
if(str[0] == 'r'){
scanf("%d", &j);
p[i].a[j][j] = 0;
}else if(str[0] == 'd'){
scanf("%d", &j);
p[i].a[j][j] = 2;
}else if(str[0] == 'a'){
scanf("%d %d", &j, &k);
p[i].a[k][j]++;
}else if(str[0] == 's'){
scanf("%d %d", &j, &k);
p[i].a[j][j] = p[i].a[k][k] = 0;
p[i].a[j][k] = p[i].a[k][j] = 1LL;
}else if(str[0] == 'i'){
scanf("%d %d", &j, &k);
for(int z=j;z<=k;z++)p[i].a[z][z] = 0;
for(int z1=j,z2=k;z1<=k;z1++,z2--)
p[i].a[z2][z1] = 1LL;
}else if(str[0] == 't'){
scanf("%d %d %d %d", &c, &j, &d, &k);
p[i].a[j][j] = c;
p[i].a[k][j] = d;
//先执行c*aj+d*ak,在执行ak = 0;
//当j == k 时,顺序需要注意
p[i].a[k][k] = 0;
}
}
p[m] = p[0];
for(i=1;i<m;i++)
p[m] = Mul(p[m], p[i]);
scanf("%d", &q);
t = Pow(p[m], q/m);
for(i=0;i<q%m;i++)
t = Mul(t, p[i]);
s = Mul(s, t);
for(i=1;i<n;i++)
printf("%lld ", s.a[1][i]%mod);
printf("%lld\n", s.a[1][n]%mod);
}
return 0;
}
matrix Pow(matrix a, int b)
{
matrix as;
memset(as.a, 0, sizeof(as.a));
for(int i=0;i<=30;i++)
as.a[i][i] = 1;
while(b)
{
if(b%2)as = Mul(as, a);
a = Mul(a, a);
b /= 2;
}
return as;
}
matrix Mul(matrix a, matrix b)
{
matrix c;
memset(c.a, 0, sizeof(c.a));
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++){
c.a[i][j] = 0;
for(int k=1;k<=n;k++)
c.a[i][j] = (c.a[i][j]+(a.a[i][k]*b.a[k][j]%mod))%mod;
}
return c;
}