HDU 2243 AC自動機 矩陣快速冪

2021-08-05 23:39:42 字數 1885 閱讀 8792

中文題,不解釋

這道題其實和poj 2778是一樣的,只是需要對矩陣有著更深刻的理解而已。我們很容易便能像poj 2778一樣求出來不包含條件字串的字串方案。只是題目中要求長度小於等於l,所以我們可以在矩陣中手動加乙個點,這個點允許從任何狀態轉移而來。這點的意義表示字串終止。也就是說如果字串轉移到這個點時候小於l,那麼字串最終長度小於l。求出來小於等於l,不包含條件字串的方案數以後,只要求出來總方案數就可以解決問題。

總方案數遞推公式很容易求出來。f[n]=26*f[n-1]+1。(+1表示上一位終止,26表示補充乙個字元)如果遞推去求,超時是必然的。這時候又要用到矩陣的性質,將遞推公式轉化為矩陣。因為遞推公式裡有兩項,所以矩陣就轉化為乙個二維矩陣。[26,1;0,1]^n[f(0),1]。利用矩陣快速冪搞出來,減去不包含條件字串的方案數就可以了。

#include 

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define up(i,l,h) for(int i=l;i#define down(i,h,l) for(int i=h-1;i>=l;i--)

#define w(a) while(a)

#define mem(a,b) memset(a,b,sizeof(a))

#define inf 0x3f3f3f3f3f3f3f3f

#define ll long long

#define ull unsigned long long

#define maxn 10000

#define eps 1e-10

#define mod 100000

#define n 26

using

namespace

std;

typedef

unsigned ll matrix[35][35];

int ch[35][26];

char st[35];

int sz;

int val[35],f[35];

matrix a,ans,temp;

void insert()

u=ch[u][x];

}val[u]=1;

}void getfail()

}w(!q.empty())

q.push(u);

int v=f[r];

f[u]=ch[v][x];

if(val[f[u]]) }}

}void buildmatrix()

}up(i,0,sz+1)

}void matrixmulti(matrix a,matrix b) }}

memcpy(a,temp,sizeof(temp));

}void quick(int n)

w(n)

matrixmulti(a,a);

n>>=1;

}}int main()

getfail();

buildmatrix();

int k=0;

up(i,0,sz)

}quick(l);

ull ansnum=0;

up(i,0,sz+1)

mem(a,0);

a[0][0]=26;

a[0][1]=a[1][1]=1;

quick(l);

printf("%i64u\n",(ans[0][0]+ans[0][1]-ansnum));

}}

hdu 2243 AC自動機 矩陣加速

給你 n 個病毒,問長度為 1,m 的,包括病毒的有多少。全都是小寫字母。和 poj 2778 有點像。不一樣的是 1 這個是求包括的,我這麼做的,加一維用來表示已經包括了病毒的狀態。2 求長度是 1,m 的。在矩陣裡面維度變成二倍。a 1 1 0 左下面的 1 就是最後所求。a是矩陣的話,就把 1...

MZ hdu 2243 AC自動機 矩陣加速

給你 n 個病毒,問長度為 1,m 的,包括病毒的有多少。全都是小寫字母。和 poj 2778 有點像。不一樣的是 1 這個是求包括的,我這麼做的,加一維用來表示已經包括了病毒的狀態。2 求長度是 1,m 的。在矩陣裡面維度變成二倍。a 1 1 0 左下面的 1 就是最後所求。a是矩陣的話,就把 1...

HDOJ 2243 AC自動機 等比矩陣求和

題目是要說小於l長度的由小寫字母組成的字串有多少個包含所給的串.從正方向想.要求出包含的.並且還要踢去重複包含的.又要加上被多踢的.整個一容斥問題了.但這題明顯是不可行的.那麼換個角度.先求出總共小於l的單詞數 26 1 26 2 26 3 26 l 然後再減去不包括所給字串的單詞.相當於把每個單詞...