Solution

考虑分开统计朝向每一个方向的所有狐狸对答案的贡献. 比如说以向右为例, 我们用箭标表示每一只狐狸的方向, 用\('\)表示当前一步移动之前的每一只狐狸的位置.

\[\begin{aligned}
\sum_{d_i = \rightarrow} x_iy_i &= \left( \sum_{d_i = \rightarrow} S \times (x_i' + 1)y_i' \right) + \left( \sum_{d_i = \uparrow} L \times x_i'y_i' \right) + \left( \sum_{d_i = \downarrow} R \times x_i' y_i' \right) \\
&= \left( \sum_{d_i = \rightarrow} S \times x_i'y_i' \right) + \left( \sum_{d_i = \rightarrow} S \times y_i' \right) + \left( \sum_{d_i = \uparrow} L \times x_i'y_i' \right) + \left( \sum_{d_i = \downarrow} R \times x_i' y_i' \right)
\end{aligned}
\]

这样一来, 我们发现只需要统计朝向每个方向的狐狸的\(\sum x\), \(\sum y\), \(\sum xy\)即可. 考虑怎么更新这几个值: 我们再多记录一个\(sum\)表示朝向每个方向的狐狸的数量.

然后我们就得到了\(4 \times 4 = 16\)个需要维护的变量.

我们建立一个\(16 \times 16\)的矩阵, 用于使得这些变量相互转移.

矩阵快速幂.

构建这个矩阵还是挺麻烦的.

总结: DP的优化除了常见的斜率/优先队列外, 不要忘了还有矩乘可用.

#include <cstdio>
#include <cstring> const long long mv[4][2] = {{1, 0}, {0, -1}, {-1, 0}, {0, 1}};
const long long MOD = 1e9 + 7;
struct matrix
{
long long a[16][16];
inline void build(long long S, long long L, long long R)
{
memset(a, 0, sizeof(a));
for (long long i = 0; i < 4; ++ i)
{
for (long long j = 0; j < 4; ++ j)
a[4 * i | j][4 * i | j] += S,
a[4 * i | j][4 * ((i - 1 + 4) % 4) | j] += R,
a[4 * i | j][4 * ((i + 1 + 4) % 4) | j] += L;
for (long long j = 0; j < 2; ++ j)
a[4 * i | j][4 * i | 2] = (a[4 * i | j][4 * i | 2] + S * mv[i][j] + MOD) % MOD,
a[4 * i | 3][4 * i | j] = (a[4 * i | 3][4 * i | j] + S * mv[i][! j] + MOD) % MOD;
}
/* for (long long i = 0; i < 16; ++ i)
{
for(long long j = 0; j < 16; ++ j) prlong longf("%d ", a[i][j]);
puts("");
} */
}
inline matrix friend operator *(matrix a, matrix b)
{
matrix res; memset(res.a, 0, sizeof res.a);
for (long long i = 0; i < 16; ++ i) for (long long j = 0; j < 16; ++ j) for (long long k = 0; k < 16; ++ k)
res.a[i][j] = (res.a[i][j] + a.a[i][k] * b.a[k][j] % MOD) % MOD;
return res;
}
}trans, a;
inline matrix power(long long x)
{
matrix res; memset(res.a, 0, sizeof res.a);
for (long long i = 0; i < 16; ++ i) res.a[i][i] = 1;
for (; x; trans = trans * trans, x >>= 1)
if (x & 1) res = res * trans;
return res;
}
int main()
{ #ifndef ONLINE_JUDGE freopen("fox.in", "r", stdin);
freopen("fox.out", "w", stdout); #endif long long T; scanf("%d", &T);
for(long long cs = 0; cs < T; ++ cs)
{
long long t, S, L, R; scanf("%lld%lld%lld%lld", &t, &S, &L, &R);
trans.build(S, L, R);
matrix res = power(t);
long long ans = 0;
for (long long i = 3; i < 16; i += 4) ans = (ans + res.a[i][2]) % MOD;
printf("%d\n", ans);
}
}

NOI模拟题4 Problem B: 小狐狸(fox)的更多相关文章

  1. NOI模拟题1 Problem A: sub

    题面 Sample Input 5 7 2 -1 -3 1 1 1 2 1 3 3 4 3 5 2 1 3 0 2 1 2 1 2 1 1 -3 2 Sample Output 2 4 5 2 HIN ...

  2. NOI模拟题6 Problem C: Circle

    Solution 首先这个矩阵, 很明显的就是Vandermonde矩阵. 我们有公式: \[ |F_n| = \prod_{1 \le j < i \le n} (a_i - a_j) \] ...

  3. NOI模拟题5 Problem A: 开场题

    Solution 注意到\(\gcd\)具有结合律: \[ \gcd(a, b, c) = \gcd(a, \gcd(b, c)) \] 因此我们从后往前, 对于每个位置\(L\), 找到每一段不同的 ...

  4. NOI模拟题4 Problem C: 填格子(board)

    Solution 首先我们要有敏锐的直觉: 我们将每一列中不选哪种颜色看作是一个序列, 则我们发现这个序列要求相邻两位的颜色不同. 我们还发现, 一个这样的序列对应两种不同的合法的棋盘, 因此统计合法 ...

  5. NOI模拟题4 Problem A: 生成树(mst)

    Solution 我们考虑答案的表达式: \[ ans = \sqrt{\frac{\sum_{i = 1}^{n - 1} (w_i - \overline{w})^2}{n - 1}} \] 其中 ...

  6. 花海漫步 NOI模拟题

    题目好像难以看懂? 题目大意 给出一个字符串\(S\),统计满足以下条件的\((i,j,p,q)\)的数量. \(i \leq j, p \leq q\) \(S[i..j],S[p..q]\)是回文 ...

  7. 神奇的矩阵 NOI模拟题

    神奇的矩阵 题目大意 有一个矩阵\(A\),第一行是给出的,接下来第\(x\)行,第\(y\)个元素的值为数字\(A_{x-1,y}\)在\(\{A_{x-1,1},A_{x-1,2},A_{x-1, ...

  8. Western Subregional of NEERC, Minsk, Wednesday, November 4, 2015 Problem K. UTF-8 Decoder 模拟题

    Problem K. UTF-8 Decoder 题目连接: http://opentrains.snarknews.info/~ejudge/team.cgi?SID=c75360ed7f2c702 ...

  9. 2010-2011 ACM-ICPC, NEERC, Moscow Subregional Contest Problem I. Interest Targeting 模拟题

    Problem I. Interest Targeting 题目连接: http://codeforces.com/gym/100714 Description A unique display ad ...

随机推荐

  1. HDU 3896 Greatest TC 双连通分量

    题意 给一个连通的无向图,有两种询问: \(a, b, c, d\),问如果删掉\(c,d\)之间的边,\(a,b\)之间是否还连通 \(a, b, c\),问如果删掉顶点\(c\),\(a,b\)之 ...

  2. bootstrap button

    样式修改 .sign-button, .sign-button:hover, .sign-button:focus, .sign-button:active, .sign-button:visited ...

  3. bash shell命令与监测的那点事(二)

    bash shell命令与监测的那点事之top 上次我们说到了ps命令,ps命令虽然在收集运行在系统上的进程信息很有用,但是也有不足之处,ps命令只能显示某个特定时间点的信息,如果你想观察频繁换进换出 ...

  4. 【Gas Station】cpp

    题目: There are N gas stations along a circular route, where the amount of gas at station i is gas[i]. ...

  5. 隐匿攻击-ICMP

    ICMP隐蔽隧道从入门到精通 概述 众所周知传统socket隧道已极少,tcp.upd大量被防御系统拦截,dns.icmp.http/https等难于禁止的协议(当然还有各种xx over dns/i ...

  6. 数据结构算法——链表的各种操作,C++和Python

    时隔已久,一直没更新博客,感觉很愧疚呀. 先贴上所有的代码.这个是用C++写的 #include "stdafx.h" //Author:Albert //Date: 2018.1 ...

  7. ValueStack、ActionContext

    笔者不知道该用哪个词来形容ValueStack.ActionContext等可以在Struts2中用来存放数据的类.这些类使用的范围不同,得到的方法也不同,下面就来一一介绍. 1. ValueStac ...

  8. mysql中游标的使用案例详解(学习笔记)(转)

    1.游标是啥玩意?简单的说:游标(cursor)就是游动的标识,啥意思呢,通俗的这么说,一条sql取出对应n条结果资源的接口/句柄,就是游标,沿着游标可以一次取出一行.我给大家准备一张图: 2.怎么使 ...

  9. 【bzoj1221】[HNOI2001] 软件开发 费用流

    题目描述 某软件公司正在规划一项n天的软件开发计划,根据开发计划第i天需要ni个软件开发人员,为了提高软件开发人员的效率,公司给软件人员提供了很多的服务,其中一项服务就是要为每个开发人员每天提供一块消 ...

  10. 【Luogu】P4219大融合(LCT)

    题目链接 LCTrotate打错尬死 容易发现本题就是问两边子树大小乘积,于是开个数组动态维护LCT每个节点虚子树上有多少点,在Access和Link的时候更新即可. #include<cstd ...