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的更多相关文章

  1. luogu4187 [USACO18JAN]Stamp Painting (dp)

    可以发现,只要存在连续k个相同的,这个情况就一定是合法情况 然而这个不太好算,我们算不存在k个相同的,然后用$m^n$把它减掉 设f[i]为前i个,没有连续k个的 显然$f[i]=m^i ,i< ...

随机推荐

  1. [Spark][kafka]kafka 生产者,消费者 互动例子

    [Spark][kafka]kafka 生产者,消费者 互动例子 # pwd/usr/local/kafka_2.11-0.10.0.1/bin 创建topic:# ./kafka-topics.sh ...

  2. .NET开源项目 QuarkDoc 一款自带极简主义属性的文档管理系统

    有些话说在前头 因为公司产品业务重构且功能拆分组件化,往后会有很多的接口文档需要留存,所以急需一款文档管理系统.当时选型要求3点: 1.不能是云平台上的Saas服务,整个系统都要在自己公司部署维护(数 ...

  3. NO NEWS IS GOOD NEWS

    从客户那传来一个噩耗:要求每个表单在保存之后,要在页面上弹一个 “ 保存成功 ” 的对话框. 客户代表志得意满地说这样用户体验更好,略带谴责意味地傲娇道,“你们早该想到的”.呵呵…… 可不是嘛,我刚入 ...

  4. 使用 OpenSSL 创建私有 CA:1 根证书

    OpenSSL 创建私有 CA 三部曲:使用 OpenSSL 创建私有 CA:1 根证书使用 OpenSSL 创建私有 CA:2 中间证书使用 OpenSSL 创建私有 CA:3 用户证书 OpenS ...

  5. lambda函数

    1.lambda函数是语法简短的匿名函数 2.lambda函数可以接受一个或多个参数 3.lambda函数只能有一个表达式 4.一般用于非重用的代码块 1)g = lambda x : x**2 g( ...

  6. 四、Input框改placeholder中字体的颜色

    Input框改placeholder中字体的颜色 input::-webkit-input-placeholder { color: #ccc; font-size: 12px; }

  7. Codeblocks 遇到的问题 Cannot open output file, permission denied

    Codeblocks下运行C++的程序时,偶尔会出现  Cannot open output file, permission denied 的问题,导致不能够编译. 在 Stack Overflow ...

  8. HDU - 1540 线段树的合并

    这个题题意我大概解释一下,就是一开始一条直线,上面的点全是联通的,有三种操作 1.操作D把从左往右第x个村庄摧毁,然后断开两边的联通. 2.询问Q节点相联通的最长长度 3.把最后破坏的村庄重建. 这个 ...

  9. Yii1.1框架关于日志的配置的简单使用

    最近开始接触新项目,新项目用的框架是Yii1.1版本的,通过看框架文档大致熟悉了解了Yii在日志方面的使用. 首先在protected/config/main.php配置文件中加入日志相关配置,如下图 ...

  10. js数据放入缓存,需要再调用

    再贴代码之前先描述下,这个技术应用的场景:一个页面的http请求次数能少点就少,这样大大提高用户体验.所以再一个页面发起一个请求,把所有数据都拿到后储存在缓存里面,你想用的时候再调用出来,这个是非常好 ...