bzoj 1009: [HNOI2008] GT 시험(AC 자동기 + 매트릭스 최적화 dp)
Time Limit: 1 Sec
Memory Limit: 162 MB
Submit: 2794
Solved: 1723
[ Submit][ Status][ Discuss]
Description
아신은 GT 시험에 지원할 준비를 하고 있는데, 수험표 번호는 N자리 X1X2...Xn(0<=Xi<=9), 그는 수험표 번호에 불길한 숫자가 나오는 것을 원하지 않는다.그의 불길한 수학 A1A2...Am(0<=Ai<=9)에는 M자리가 있는데, 나타나지 않는 것은 X1X2...Xn에 A1A2와 같은 단락이 없습니다.Am. A1과 X1은 0일 수 있습니다.
Input
첫 번째 행에 N, M, K. 를 입력하고 다음 행에 M 비트 수를 입력합니다.N<=10^9,M<=20,K<=1000
Output
아신은 불길한 숫자가 나타나지 않는 번호가 몇 가지가 있는지 알고 싶어한다. 출력 모드 K에서 나머지 결과를 얻는다.
Sample Input
4 3 100 111
Sample Output
81
HINT
Source
[ Submit][ Status][ Discuss]
문제풀이: 이 문제의 폭력 dp는 텍스트 생성기와 같다.
f[i][j]는 원수열의 i위가 트리의 J번째 노드와 일치한다는 것을 나타낸다.
그리고 최적화 매트릭스를 구축한다. 만약에 현재 노드가 합법적이고 그의 아들도 합법적이라면 그는 그의 아들을 밀어낼 수 있다. 그래서 최적화 매트릭스에서 A[I][CH[I][J]]=1.
그리고 A^N은 옮긴 결과입니다.
폭력DP에 의하면 첫 번째 단계는 0이라는 노드와 연결된 노드만 업데이트되는 것을 알 수 있기 때문에 초기 행렬은 1이다×tot의 01 행렬.
마지막으로 초기 행렬을 다시 사용하고 A를 곱하면 결과를 누적하면 답이 된다.
#include
#include
#include
#include
#include
#include
using namespace std;
int n,m,p,a[1000],tot;
int ch[200][26],fail[1003],isend[1000];
int f[2][1000],cnt;
int N;
struct data
{
int a[100][100];
}e;
void insert()
{
int now=0;
for (int i=1;i<=m;i++)
{
if (!ch[now][a[i]]) ch[now][a[i]]=++tot;
now=ch[now][a[i]];
}
isend[now]=1;
}
void makefail()
{
int now=0;
queue p;
for (int i=0;i<=9;i++)
if (ch[now][i]) p.push(ch[now][i]);
while (!p.empty())
{
int now=p.front(); p.pop();
for (int i=0;i<=9;i++)
{
if (!ch[now][i])
{
ch[now][i]=ch[fail[now]][i];
continue;
}
int x=ch[now][i];
fail[x]=ch[fail[now]][i];
if (isend[fail[x]]) isend[x]=1;
p.push(x);
}
}
}
void clear(data &x)
{
for (int i=1;i<=N;i++)
for (int j=1;j<=N;j++)
x.a[i][j]=0;
}
void change(data &a,data b)
{
for (int i=1;i<=N;i++)
for(int j=1;j<=N;j++)
a.a[i][j]=b.a[i][j];
}
data mul(data a,data b)
{
data c;
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]%p)%p;
}
return c;
}
data pow(data num,int x)
{
data ans; clear(ans);
for (int i=1;i<=N;i++) ans.a[i][i]=1;
data base; change(base,num);
while(x)
{
if (x&1) ans=mul(ans,base);
x>>=1;
base=mul(base,base);
}
return ans;
}
void build()
{
N=tot; clear(e);
for (int i=1;i<=tot;i++)
{
if (isend[i]) continue;
for (int j=0;j<=9;j++)
{
if (isend[ch[i][j]]) continue;
e.a[i][ch[i][j]]=1;
}
}
}
int main()
{
scanf("%d%d%d",&n,&m,&p);
char s[30]; scanf("%s",s+1);
for (int i=1;i<=m;i++)
a[i]=s[i]-'0';
insert();
for (int i=0;i<=9;i++)
if (!ch[0][i])
ch[0][i]=++tot;
makefail();
build();
data ans=pow(e,n-1);
for (int i=0;i<=tot;i++)
{
if (isend[i]) continue;
for (int j=0;j<=9;j++)
f[1][ch[i][j]]+=(i==0);
}
int t[100]; int sum=0;
for (int j=1;j<=N;j++)
{
t[j]=0;
for (int k=1;k<=N;k++)
t[j]=(t[j]+f[1][k]*ans.a[k][j]%p)%p;
sum=(sum+t[j])%p;
}
printf("%d
",sum);
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
01 가방, 완전 가방, 다중 가방 dp(동적 기획 입문 dp)01 가방은 2진법으로 직접 표시할 수 있지만 데이터 양이 너무 많으면 시간을 초과하는 것이 폭력이다.01 가방의 사상은 바로 이 물품에 대해 내가 넣은 가치가 큰지 안 넣은 가치가 큰지 비교하여 방정식 f[i][v...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.