SPOJ 1676 矩阵乘法+DP

题意:

给定N (1 ≤ N ≤ 10)个长度不超过6的单词,求由大写字母组成长度为L的包含至少一个给定单词的字符串有多少种,答案 mod 10007,(1 ≤ L ≤ 10^6)。

 

题解:

这个题最早是在一个关于trie图的论文中看到了,最近jzh又讲到了这个题,于是就把它做了~

大致有两种做法,两种方法都需要矩阵乘法加速

1、trie图中的dp

2、直接人工减少转移数量

具体做法点击这里

 

大致思路就是将不可能构成单词的前缀合成一类,然后胡搞就行了。

 

View Code
  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 #include <string>
  5 #include <cstdlib>
  6 #include <algorithm>
  7 #include <map>
  8 
  9 #define N 60
 10 #define SIZE 70
 11 #define mod 10007
 12 
 13 using namespace std;
 14 
 15 map<string,int> mp;
 16 
 17 int n,cnt,res,m;
 18 string str[N],prefix[SIZE];
 19 
 20 struct MT
 21 {
 22     int x,y;
 23     int mt[SIZE][SIZE];
 24 }zy,ans;
 25 
 26 inline MT operator *(MT a,MT b)
 27 {
 28     MT c; memset(c.mt,0,sizeof c.mt);
 29     c.x=a.x; c.y=b.y;
 30     for(int i=1;i<=c.x;i++)
 31         for(int j=1;j<=c.y;j++)
 32             for(int k=1;k<=a.y;k++)
 33             {
 34                 c.mt[i][j]+=a.mt[i][k]*b.mt[k][j];
 35                 if(c.mt[i][j]>=mod) c.mt[i][j]%=mod;
 36             }
 37     return c;
 38 }
 39 
 40 inline void read()
 41 {
 42     mp.clear();
 43     for(int i=1;i<=n;i++)
 44     {
 45         cin>>str[i];
 46         mp[str[i]]=520;
 47     }
 48 }
 49 
 50 inline bool check(string x)//检查x是否是合法的前缀 
 51 {
 52     string::size_type pos;
 53     for(int i=1;i<=n;i++)
 54     {
 55         pos=x.find(str[i]);
 56         if(pos!=x.npos) return false;
 57     }
 58     return true;
 59 }
 60 
 61 inline void get_det()
 62 {
 63     memset(zy.mt,0,sizeof zy.mt);
 64     cnt=0;
 65     for(int i=1;i<=n;i++)
 66     {
 67         string tmp;
 68         for(int j=0;j<str[i].length();j++)
 69         {
 70             tmp.push_back(str[i][j]);
 71             if(check(tmp)&&mp[tmp]==0)
 72             {
 73                 mp[tmp]=++cnt;//前缀字符串的映射 
 74                 prefix[cnt]=tmp;//前缀字符串 
 75             }
 76         }
 77     }
 78     zy.x=zy.y=cnt+1;
 79     
 80     string tmp;
 81     for(int i=1;i<=cnt;i++)
 82         for(int j=0;j<26;j++)
 83         {
 84             tmp=prefix[i]; tmp.push_back(j+'A');
 85             for(int k=tmp.length();k>=0;k--)
 86             {
 87                 if(k==0)
 88                 {
 89                     zy.mt[cnt+1][mp[prefix[i]]]++;//不存在后缀是已知的前缀 
 90                     break;
 91                 }
 92                 else 
 93                 {
 94                     string tp;
 95                     for(int p=tmp.length()-k;p<tmp.length();p++)
 96                         tp.push_back(tmp[p]);
 97                     if(mp[tp]==520) break;//出现单词,不合法 
 98                     else if(mp[tp]!=0) {zy.mt[mp[tp]][mp[prefix[i]]]++;break;}//存在最大的后缀是已知的前缀 
 99                 }
100             }
101         }
102     for(int i=0;i<26;i++)
103     {
104         string sy;
105         sy.push_back(i+'A');
106         if(mp[sy]==0) zy.mt[cnt+1][cnt+1]++;
107         else if(mp[sy]==520) continue;
108         else zy.mt[mp[sy]][cnt+1]++;
109     }
110     
111     ans.x=cnt+1; ans.y=1;
112     memset(ans.mt,0,sizeof ans.mt);
113     ans.mt[cnt+1][1]=1;
114 }
115 
116 inline int qs(int a,int b)
117 {
118     int res=1;
119     while(b)
120     {
121         if(b&1) res=(res*a)%mod;
122         a=(a*a)%mod;
123         b>>=1;
124     }
125     return res;
126 }
127 
128 inline void go()
129 {
130     get_det();
131     res=qs(26,m);
132     while(m)
133     {
134         if(m&1) ans=zy*ans;
135         zy=zy*zy;
136         m>>=1;
137     }
138     
139     int tmp=0;
140     for(int i=1;i<=cnt+1;i++) tmp=(tmp+ans.mt[i][1])%mod;
141     res-=tmp;
142     printf("%d\n",(res+mod)%mod);
143 }
144 
145 int main()
146 {
147     while(scanf("%d%d",&n,&m)!=EOF) read(),go();
148     return 0;
149 }

 

 

转载于:https://www.cnblogs.com/proverbs/archive/2013/02/17/2914168.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/400875.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

go-zero微服务实战系列(三、API定义和表结构设计)

&#x1f680; 优质资源分享 &#x1f680; 学习路线指引&#xff08;点击解锁&#xff09;知识定位人群定位&#x1f9e1; Python实战微信订餐小程序 &#x1f9e1;进阶级本课程是python flask微信小程序的完美结合&#xff0c;从项目搭建到腾讯云部署上线&#xff0c;打造一…

STM32 串口DMA接收 Openmv / K210 整数、小数字符串数据 (基于HAL库)

目录前言一、工程配置二、串口DMA部分代码1.源文件UART_DMA.c2.头文件UART_DMA.h3.stm32f1xx_it.c的修改4.串口收发DMA测试三、字符串数字提取代码1.源文件NumAndStr.c:2.头文件NumAndStr.h:3.测试:四、Openmv / K210 发送、STM32接收测试总结修订版本UART_DMA.cUART_DMA.h平台…

6000字|22张图 带你彻底弄懂Zookeeper分布式锁

&#x1f680; 优质资源分享 &#x1f680; 学习路线指引&#xff08;点击解锁&#xff09;知识定位人群定位&#x1f9e1; Python实战微信订餐小程序 &#x1f9e1;进阶级本课程是python flask微信小程序的完美结合&#xff0c;从项目搭建到腾讯云部署上线&#xff0c;打造一…

【HDU2896】病毒侵袭——ac自动机

网上很多代码都略显繁琐&#xff0c;看了一下yy dalao的代码感觉很好&#xff0c;但他懒得打题解&#xff08;好吧我也是 以0为根节点的话&#xff0c;我把yy的一段代码删了改用fail[c]x0?0:ch[fail[x]][i];来实现特判&#xff0c;效果还不错&#xff01;也算是AC自动机的模版…

经典 HTML5 Javascript 俄罗斯方块游戏

Blockrain.js 是一个使用 HTML5 & JavaScript 开发的经典俄罗斯方块游戏。只需要复制和粘贴一段代码就可以玩起来了。最重要的是&#xff0c;它是响应式的&#xff0c;无论你的显示屏多么宽都能自动匹配。你可以自定义你想要的颜色以适应您的网站&#xff0c;也可以调整方块…

【电赛PID半天入门】从接触编码器到调出好康的PID波形

从接触编码器到调出好康的PID波形认识电机及编码器只需动动手指&#xff0c;就能让STM32得到电机转过的角度让电机转起来认识PID控制①比例调节器②积分调节③微分调节④比例积分微分调节数字PID调节器&#xff08;1&#xff09;数字PID位置型控制算法&#xff08;2&#xff09…

算法的复杂度分析

&#x1f680; 优质资源分享 &#x1f680; 学习路线指引&#xff08;点击解锁&#xff09;知识定位人群定位&#x1f9e1; Python实战微信订餐小程序 &#x1f9e1;进阶级本课程是python flask微信小程序的完美结合&#xff0c;从项目搭建到腾讯云部署上线&#xff0c;打造一…

PHP面向对象 封装与继承

知识点&#xff1a; PHP封装三个关键词&#xff1a; 一、public 公有的&#xff0c;被public修饰的属性和方法&#xff0c;对象可以任意访问和调用 二、private 私有的&#xff0c;被private修饰的属性和方法&#xff0c;只能在类内部的方法可以进行调用&#xff0c;或者被子类…

POJ 1380 坐标旋转

题意&#xff1a; 问第二个矩形能不能放进第一个矩形中。 题解&#xff1a; 暴力旋转第二个矩形&#xff0c;判断左右、上下是否同时小于第一个矩形 当然&#xff0c;数学推导也可以&#xff0c;挺简单的相似神马的胡搞就行~ View Code 1 #include <iostream>2 #include…

MSP430F5529 DriverLib 库函数学习笔记(一)时钟配置和闪烁LED

目录一、新建工程二、时钟树时钟系统结构时钟系统的原理时钟树配置实战三、点灯工程师封装好的初始化函数平台&#xff1a;Code Composer Studio 10.3.1 MSP430F5529 LaunchPad™ Development Kit (MSP‑EXP430F5529LP) 一、新建工程 二、时钟树 时钟系统结构 &#xff08;1&…

libcurl上传文件

libcurl参数很多&#xff0c;一不小心就容易遇到问题。曾经就遇到过一个很蛋疼的问题&#xff1a;libcurl断点下载>> 这里主要汇总一下&#xff0c;libcurl上传的二种方式&#xff1a; 1、直接上传文件&#xff0c;类似form表单<input type”file” />&#xff0c;…

MSP430F5529 DriverLib 库函数学习笔记(二)GPIO

目录硬知识一、MSP430单片机端口概述二、通用IO端口输出特性三、端口P1和P21&#xff0e;输入寄存器PxIN2&#xff0e;输出寄存器PxOUT3&#xff0e;方向寄存器PxDIR4&#xff0e;上拉/下拉电阻使能寄存器PxREN5&#xff0e;输出驱动能力调节寄存器PxDS6&#xff0e;功能选择寄…

MSP430F5529 DriverLib 库函数学习笔记(三)认识中断

目录一、硬知识中断的基本概念MSP430单片机中断源中断响应过程中断返回过程中断嵌套二、msp430f5529.h中所列的中断向量宏定义平台&#xff1a;Code Composer Studio 10.3.1 MSP430F5529 LaunchPad™ Development Kit (MSP‑EXP430F5529LP) 一、硬知识 中断的基本概念 中断…

推荐系统相关算法

摘要&#xff1a; 热门推荐 协同过滤算法 矩阵分解 基于内容的推荐&#xff08;文本&#xff0c;标签&#xff0c;特征/profile&#xff09; 基于图的算法 内容&#xff1a; 热门推荐&#xff1a; 热门推荐本质上是一个排行榜&#xff0c;可能会考虑到时间衰减&#xff0c;商品…

冒泡排序的简单理解

&#x1f680; 优质资源分享 &#x1f680; 学习路线指引&#xff08;点击解锁&#xff09;知识定位人群定位&#x1f9e1; Python实战微信订餐小程序 &#x1f9e1;进阶级本课程是python flask微信小程序的完美结合&#xff0c;从项目搭建到腾讯云部署上线&#xff0c;打造一…

司机和售票员问题 信号signal注册一例

#include <stdio.h> #include <stdlib.h> #include <signal.h>pid_t pid;void driver_handler(int signo) //司机的信号处理函数 {if (signo SIGUSR1)printf("Lets go!\n");if (signo SIGUSR2)printf("Stop the bus!\n");if (signo …

MSP430F5529 DriverLib 库函数学习笔记(四)UART通信

目录硬知识USCI通信模块USCI的UART模式1. USCI初始化和复位2. 异步通信字符格式3. 异步多机通信模式4. 自动波特率检测5. IrDA编码和解码6. 自动错误检测7. USCI接收使能8. USCI发送使能9. UART波特率的产生10. UART波特率的设置&#xff08;重要&#xff09;&#xff08;1&…

MSP430F5529 DriverLib 库函数学习笔记(四点五)printf打印输出

目录代码实现使相应工程支持打印浮点数实验结果平台&#xff1a;Code Composer Studio 10.3.1 MSP430F5529 LaunchPad™ Development Kit (MSP‑EXP430F5529LP)代码实现 重定向fputc(int ch, FILE *f)直接使用printf的方法只有字符串和%s打印正常&#xff0c;数字打印不出来…

flag

mark, to remember

MSP430F5529 DriverLib 库函数学习笔记(五)定时器A

目录硬知识定时器A 16位定时器原理&#xff08;1&#xff09;时钟源选择和分频器&#xff08;2&#xff09;Timer_A工作模式&#xff08;3&#xff09;捕获/比较模块&#xff08;4&#xff09;Timer_A中断&#xff08;重要&#xff09;定时器A API (机翻)定时器A配置和控制的函…