pro1
ACM-ICPC 2017 Asia Urumqi: H. Count Numbers
2017乌鲁木齐区域赛 矩阵快速幂+dp
小技巧摘录
当矩阵的幂 会爆long long时,不想用java的话,可以这样转化
矩阵的幂可以转换为 M ^(a^b-9)
a^b - 9 = a^(b/2)*a^(b-b/2)-9
我们来看这个问题 a*b-9,可以转换成b*(a-1)+ b-9 ,目的是去掉负号
然后就可以转换成( M^b )^(a-1) * M^(b-9);
这样就要求3次快速幂,其中M^(b-9) 和 M^b 可以继续合并以加快速度。
code在最后。
pro2
HDU 6155 dp+矩阵+线段树
参考博客
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6155
给出一个长度为n的01序列以及Q个操作,操作分两类,一种是将[L,R]内的01序列翻转,二是求出[L,R]中包含多少不同的子序列。
这个题目一是要想到dp方程,二是要想到利用矩阵去表示0和1,同时还要巧妙的表示出首项,第三点是翻转,只要第二点能够想到,那么第三点就不难推出来。
pro3
矩阵快速幂: 网易2017实习生编程题 魔力手环
描述:
小易拥有一个拥有魔力的手环上面有n个数字(构成一个环),当这个魔力手环每次使用魔力的时候就会发生一种奇特的变化:每个数字会变成自己跟后面一个数字的和(最后一个数字的后面一个数字是第一个),一旦某个位置的数字大于等于100就马上对100取模(比如某个位置变为103,就会自动变为3).现在给出这个魔力手环的构成,请你计算出使用k次魔力之后魔力手环的状态。
输入描述:
输入数据包括两行:
第一行为两个整数n(2 ≤ n ≤ 50)和k(1 ≤ k ≤ 2000000000),以空格分隔
第二行为魔力手环初始的n个数,以空格分隔。范围都在0至99.
输出描述:
输出魔力手环使用k次之后的状态,以空格分隔,行末无空格。
输入例子:
3 2
1 2 3
输出例子:
8 9 7
每一次变化,可以看成乘以一个矩阵
1 1 0 0 0 …0
0 1 1 0 0 …0
0 0 1 1 0 …0
.
.
.
1 0 0 0 0… 1
最终结果是乘以这个矩阵k次。使用矩阵快速幂求解。
To-do list
https://blog.csdn.net/catherinetang0919/article/details/23207571
https://blog.csdn.net/Mys_C_K/article/details/80429262
pro1code:
java版code:
import java.util.*;
import java.math.*;
public class Main {
static long MOD;
static class lenka
{
long a[][]=new long[20][20];
lenka()
{
for(int i=0;i<18;i++)
{
for(int j=0;j<18;j++)a[i][j]=0;
}
}
}
static lenka cla(lenka a,lenka b)
{
lenka c=new lenka();
for(int i=0;i<18;i++)
{
for(int j=0;j<18;j++)
{
for(int k=0;k<18;k++)
{
c.a[i][j]+=a.a[i][k]*b.a[k][j]%MOD;
c.a[i][j]%=MOD;
}
}
}
return c;
}
static long POW(BigInteger n)
{
lenka a=new lenka();
lenka res=new lenka();
for(int i=0;i<18;i++)res.a[i][i]=1;
for(int i=0;i<9;i++)
{
a.a[i][0]=1;
a.a[i][9]=i+1;
}
for(int i=1;i<9;i++)
{
a.a[i-1][i]=1;
a.a[i+8][i+9]=1;
}
for(int i=9;i<18;i++)a.a[i][9]=10;
while(n.compareTo(BigInteger.ZERO)>0)
{
if(n.mod(new BigInteger("2")).compareTo(BigInteger.ONE)==0)res=cla(a,res);
a=cla(a,a);
n=n.divide(new BigInteger("2"));
}
long d[]={128,64,32,16,8,4,2,1,1,23817625,2165227,196833,17891,1625,147,13,1,0};
long ans=0;
for(int i=0;i<18;i++)
{
ans+=(d[i]%MOD)*res.a[i][17]%MOD;
ans%=MOD;
}
return ans;
}
public static void main(String args[])
{
Scanner cin=new Scanner(System.in);
int T=cin.nextInt();
while((T--)>0)
{
BigInteger a=cin.nextBigInteger();
int b=cin.nextInt();
MOD=cin.nextLong();
System.out.println(POW(a.pow(b)));
}
}
}
Pro2 code:
#include <bits/stdc++.h>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
int n,q;
const int maxn=1e5+9;
const long long mod=1e9+7;
struct matrix
{
long long m[3][3];
};
const matrix mp[2]= {{1,0,0,1,1,0,1,0,1},{1,1,0,0,1,0,0,1,1}};
matrix data[maxn<<2];
int f[maxn<<2];
char s[maxn];
matrix mul(matrix a,matrix b)
{
matrix tmp;
for(int i=0; i<3; i++)
{
for(int j=0; j<3; j++)
{
tmp.m[i][j]=0;
for(int k=0; k<3; k++)
tmp.m[i][j]+=(a.m[i][k]*b.m[k][j])%mod;
tmp.m[i][j]%=mod;
}
}
return tmp;
}
void flip(matrix &x)
{
swap(x.m[0][0], x.m[0][1]);
swap(x.m[1][0], x.m[1][1]);
swap(x.m[2][0], x.m[2][1]);
swap(x.m[0][0], x.m[1][0]);
swap(x.m[0][1], x.m[1][1]);
}
void pushup(int rt)
{
data[rt]= mul(data[rt<<1],data[rt<<1|1]);
}
void pushdown(int rt)
{
if(f[rt])
{
flip(data[rt<<1]);
flip(data[rt<<1|1]);
f[rt<<1]^=f[rt];
f[rt<<1|1]^=f[rt];
f[rt]=0;
}
}
void build(int l,int r,int rt)
{
f[rt]=0;
if(l==r)
{
int t=s[l]-'0';
data[rt]=mp[t];
return;
}
int m=r+l>>1;
build(lson);
build(rson);
pushup(rt);
}
void update(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
f[rt]=1-f[rt];
flip(data[rt]);
return;
}
int m=l+r>>1;
pushdown(rt);
if(L<=m) update(L,R,lson);
if(m<R) update(L,R,rson);
pushup(rt);
}
matrix query(int L,int R,int l,int r,int rt)
{
if(L==l&&r==R)
return data[rt];
int m=l+r>>1;
pushdown(rt);
if(R<=m) return query(L,R,lson);
else if(L>m) return query(L,R,rson);
else return mul(query(L,m,lson),query(m+1,R,rson));
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&q);
scanf("%s",s+1);
build(1,n,1);
while(q--)
{
int op,l,r;
scanf("%d%d%d",&op,&l,&r);
if(op==1)
update(l,r,1,n,1);
else
{
matrix x=query(l,r,1,n,1);
printf("%I64d\n",(x.m[2][0]+x.m[2][1])%mod);
}
}
}
return 0;
}