luogu4187
P4187 [USACO18JAN]Stamp Painting
样例
input
3 2 2
output
6
input
6 10 5
output
190
sol:首先可以发现,对于合法的序列,只要有一串至少连续K个相同的就可以了,其他没有限制
这当然是可以dp辣
dp[i][j]表示前i位没有,当前有j个连续相同,前面没有出现连续K个相同
统计答案的时候就是∑i={K,n} dp[i][K]*Ksm(m,n-i)
转移挺容易的
dp[1][1]=m
dp[i][1]=(m-1)*∑j={1,K-1} dp[i-1][j]
dp[i][j=(2~K)] = dp[i-1][j-1]
但是就这样裸的暴力肯定是n2的
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
inline ll read()
{
ll s=;
bool f=;
char ch=' ';
while(!isdigit(ch))
{
f|=(ch=='-'); ch=getchar();
}
while(isdigit(ch))
{
s=(s<<)+(s<<)+(ch^); ch=getchar();
}
return (f)?(-s):(s);
}
#define R(x) x=read()
inline void write(ll x)
{
if(x<)
{
putchar('-'); x=-x;
}
if(x<)
{
putchar(x+''); return;
}
write(x/);
putchar((x%)+'');
return;
}
#define W(x) write(x),putchar(' ')
#define Wl(x) write(x),putchar('\n')
const ll Mod=;
const int N=;
int n,m,K;
ll dp[N][N]; //dp[i]表示前i位没有,当前有j个连续相同,前面没有出现连续K个相同
inline void Ad(ll &x,ll y)
{
x+=y;
x-=(x>=Mod)?Mod:;
}
inline ll Ksm(ll x,ll y)
{
ll ans=;
while(y)
{
if(y&) ans=ans*x%Mod;
x=x*x%Mod;
y>>=;
}
return ans;
}
int main()
{
freopen("data.in","r",stdin);
freopen("baoli.out","w",stdout);
int i,j;
ll ans=;
R(n); R(m); R(K);
dp[][]=m;
for(i=;i<=n;i++)
{
for(j=;j<=(K-)&&j<=(i-);j++) Ad(dp[i][],dp[i-][j]*(m-)%Mod);
for(j=;j<=K&&j<=i;j++)
{
dp[i][j]=dp[i-][j-];
}
}
// for(i=1;i<=n;i++)
// {
// for(j=1;j<=K;j++) W(dp[i][j]);
// puts("");
// }
for(i=K;i<=n;i++) Ad(ans,dp[i][K]*Ksm(m,n-i)%Mod);
Wl(ans);
return ;
}
/*
input
3 2 2
output
6
*/
然后面临的问题就是怎么优化这个dp,容易发现其实每次除了第一位,另外都是不变的(向右移一位而已),所以只要更新第一位的值可以了
有这样两个队列
1 2 3 4 5 Head=10 Tail=14
x 1 2 3 4 Head=9 Tail=13
发现了吗,只要搞一个队列,每次Head-1,Tail-1就会向左移一位,那个红色的x就是要更新的值了
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
inline ll read()
{
ll s=;
bool f=;
char ch=' ';
while(!isdigit(ch))
{
f|=(ch=='-'); ch=getchar();
}
while(isdigit(ch))
{
s=(s<<)+(s<<)+(ch^); ch=getchar();
}
return (f)?(-s):(s);
}
#define R(x) x=read()
inline void write(ll x)
{
if(x<)
{
putchar('-'); x=-x;
}
if(x<)
{
putchar(x+''); return;
}
write(x/);
putchar((x%)+'');
return;
}
#define W(x) write(x),putchar(' ')
#define Wl(x) write(x),putchar('\n')
const ll Mod=;
const int N=;
int n,m,K;
ll dp[N]; //dp[j]表示前i位(已经滚掉)没有,当前有j个连续相同,前面没有出现连续K个相同
ll Queue[N<<];
ll Bin[N];
inline void Ad(ll &x,ll y)
{
x+=y;
x-=(x>=Mod)?Mod:;
x+=(x<)?Mod:;
}
int main()
{
freopen("data.in","r",stdin);
freopen("my.out","w",stdout);
int i;
ll Sum=,ans=;
R(n); R(m); R(K);
dp[]=m; for(i=;i<=K;i++) dp[i]=;
Sum=m;
for(i=;i<=K;i++) Queue[n+i]=dp[i];
Bin[]=; for(i=;i<=n;i++) Bin[i]=Bin[i-]*m%Mod;
int Head=n+,Tail=n+K;
Ad(ans,Queue[Tail]*Bin[n-]%Mod);
for(i=;i<=n;i++)
{
Queue[Head-]=(Sum-Queue[Tail]+Mod)*(m-)%Mod;
Ad(Sum,Queue[Head-]);
Ad(Sum,(-)*Queue[Tail]);
Head--;
Tail--;
// for(int j=Head;j<=Tail;j++) W(Queue[j]);
// puts("");
Ad(ans,Queue[Tail]*Bin[n-i]%Mod);
}
Wl(ans);
return ;
}
/*
input
3 2 2
output
6 input
6 10 5
output
190
*/
/*
1 2 3 4 5 Head=10 Tail=14
1 2 3 4 Head=9 Tail=13
*/
Ps:最后附上对拍
:loop
make.exe
luogu4187.exe
baoli.exe
fc my.out baoli.out
if not errorlevel goto loop
pause
goto loop
pai
#include <bits/stdc++.h>
using namespace std;
typedef int ll;
inline ll read()
{
ll s=;
bool f=;
char ch=' ';
while(!isdigit(ch))
{
f|=(ch=='-'); ch=getchar();
}
while(isdigit(ch))
{
s=(s<<)+(s<<)+(ch^); ch=getchar();
}
return (f)?(-s):(s);
}
#define R(x) x=read()
inline void write(ll x)
{
if(x<)
{
putchar('-'); x=-x;
}
if(x<)
{
putchar(x+''); return;
}
write(x/);
putchar((x%)+'');
return;
}
#define W(x) write(x),putchar(' ')
#define Wl(x) write(x),putchar('\n')
const int Mod=;
int main()
{
freopen("data.in","w",stdout);
srand(time(NULL));
int n,m,k;
n=rand()%Mod+;
m=rand()%Mod+;
k=rand()%n+;
W(n); W(m); Wl(k);
return ;
}
make
luogu4187的更多相关文章
- luogu4187 [USACO18JAN]Stamp Painting (dp)
可以发现,只要存在连续k个相同的,这个情况就一定是合法情况 然而这个不太好算,我们算不存在k个相同的,然后用$m^n$把它减掉 设f[i]为前i个,没有连续k个的 显然$f[i]=m^i ,i< ...
随机推荐
- 【原创】jssh linux scp ssh 免密登录开源工具
项目名 JSSH git地址: https://gitee.com/chejiangyi/jssh 项目介绍 linux scp(文件上传,下载) shell命令的java ssh jar和linux ...
- [03] SpringBoot+MyBatis+Shiro搭建杂谈
0.写在前面的话 一直想能仿公司框架的形式,着手做一个简单的脚手架,一来是带着目标性能更好地学习,接触新的技术,另外自己如果有什么想要实现的简单需求,就可以进行快速开发,主要还是希望能在权限上有所控制 ...
- c# 设置IE浏览器版本运行程序-设置webBrowser对应的IE内核版本来运行
//通常情况下,我们直接调用C#的webBrowser控件,默认的浏览器内核是IE7. 那么如何修改控件调用的默认浏览器版本呢?using System; using System.Collecti ...
- .NET-记一次架构优化实战与方案-梳理篇
目录 .NET-记一次架构优化实战与方案-梳理篇 .NET-记一次架构优化实战与方案-前端优化 .NET-记一次架构优化实战与方案-底层服务优化 前言 程序员输出是他敲写的代码,那么输入就是他思考好的 ...
- mysqlfrm
mysqlfrm可基于frm文件生成对应的表结构.常用于数据恢复场景. 其有两种操作模式. 1. 创建一个临时实例来解析frm文件. 2. 使用诊断模式解析frm文件. 以下表进行测试,看看, 1. ...
- elasticsearch开启外网访问
默认情况下,Elastic 只允许本机访问,如果需要远程访问,可以修改 Elastic 安装目录的config/elasticsearch.yml文件,去掉network.host的注释,将它的值改成 ...
- TCP 原理
一.分组交换网络 古老的电话通信,一根电缆,两个用户设备通信 计算机中的两个设备节点通信:分组网络 计算机网络采取分组交换技术,意思就是我有[一块数据]要发给对方,那我会把这[一块数据]分成N份[ ...
- java中的代码块是什么意思,怎么用
代码块是一种常见的代码形式.他用大括号“{}”将多行代码封装在一起,形成一个独立的代码区,这就构成了代码块.代码块的格式如下: 方法/步骤 普通代码块:是最常见的代码块,在方法里用一对“{ ...
- 常用ASCII码对照表
- hadoop实例-网站用户行为分析
一.数据集 网站用户购物行为数据集2030万条,包括raw_user.csv(2000万条)和small_user.csv(30万条,适合新手) 字段说明: user_id 用户编号,item_id ...