题目链接

题意

给出参数\(C_1,C_2,P\)按如下方式生成一个长度为\(n \times m\)的序列\(x\):

\(x_0 = C_1,x_1=C2\)

\(x_i=(x_{i-1}+x_{i-1}) \% P \; (i > 1)\)

然后按如下方式生成一个长度为\(n \times m\)的序列\(a\)

\[a_i=\sum\limits_{j=0}^ix_j^2\%P
\]

然后现在进行\(Q\)次操作,每次操作给出两个参数\(k1,k2\)。表示交换\(k1,k2\)的值。

然后把序列\(a\)按顺序放到一个\(n \times m\)的网格中。

要求出一种方案,使得从\((1,1)\)走到\((n,m)\),所经过的数字排列起来字典序最小。

思路

容易发现,其实就是快速求出\(a_i\)。

然后就推一下式子。

\[x_i^2=x_{i-1}^2+2x_{i-1}x_{i-2}+x_{i-2}^2
\]

\[x_{i-1}^2=x_i^2-x_{i-2}^2-2x_{i-1}x_{i-2}
\]

\[x_{i-1}^2=(x_i+x_{i-2})\times(x_i-x_{i-2}) - 2x_{i-1}x_{i-2}
\]

\[x_{i-1}^2=x_{i-1}(x_i+x_{i-2}) - 2x_{i-1}x_{i-2}
\]

\[x_{i-1}^2=x_ix_{i-1}+x_{i-1}x_{i-2}-2x_{i-1}x_{i-2}
\]

\[x_{i-1}^2=x_ix_{i-1}-x_{i-1}x_{i-2}
\]

也就是说

\[x_i^2=x_{i+1}x_i-x_ix_{i-1}
\]

这样也就是容易得到

\[a_i=x_{i+1}x_i-C_1(C_2-C_1)
\]

所以只要可以快速的求出斐波那契数列第\(i\)项就可以了。

如果直接每次矩阵快速幂会\(TLE\)

所以先预处理出\(fbi_1,fbi_2,fbi_3...fbi_m\)和\(fbi_m,fbi_{2m},fbi_{3m}...fbi{nm}\)的转移矩阵。

对于第\(i\)行第\(j\)列的数,直接\(O(2^3)\)求出

代码

#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<cstring>
#include<bitset>
#include<map>
using namespace std;
typedef long long ll;
const int N = 500000 + 100,INF = 1e9 + 7;
map<ll,ll>ma;
ll read() {
ll x=0,f=1;char c=getchar();
while(c<'0'||c>'9') {
if(c=='-') f=-1;
c=getchar();
}
while(c>='0'&&c<='9') {
x=x*10+c-'0';
c=getchar();
}
return x*f;
}
int C1,C2,mod,n,m,Q;
namespace FBI {
struct node {
int a[3][3],n,m;
node() {
memset(a,0,sizeof(a));
}
node(int x) {
n = m = x;
memset(a,0,sizeof(a));
for(int i = 1;i <= x;++i) a[i][i] = 1;
}
node(int x,int y) {
n = x,m = y;
memset(a,0,sizeof(a));
}
};
node operator * (const node &A,const node &B) {
int n = A.n,m = B.m,K = A.m;
node ret(n,m);
for(int k = 1;k <= K;++k) {
for(int i = 1;i <= n;++i) {
for(int j = 1;j <= m;++j) {
ret.a[i][j] += 1ll * A.a[i][k] * B.a[k][j] % mod;
ret.a[i][j] %= mod;
}
}
}
return ret;
}
node fbi(1,2),tmp(2,2),lin[N],row[N];
void pre() {
fbi.a[1][1] = C2,fbi.a[1][2] = C1;
tmp.a[1][1] = tmp.a[1][2] = tmp.a[2][1] = 1; row[0].n = row[0].m = 2;row[0].a[1][1] = row[0].a[2][2] = 1;
for(int i = 1;i <= m;++i) row[i] = row[i - 1] * tmp; lin[0].n = lin[0].m = 2;
lin[0].a[1][1] = lin[0].a[2][2] = 1;
for(int i = 1;i <= n;++i) lin[i] = lin[i - 1] * row[m];
}
int solve(ll x) {
if(x == -1) return (C2 - C1 + mod) % mod;
if(x == 0) return C1;
if(x == 1) return C2;
--x;
int y = x % m;
x /= m;
return (fbi * lin[x] * row[y]).a[1][1];
}
int main(ll x) {
return (1ll * solve(x + 1) * solve(x) % mod - 1ll * C1 * (C2 - C1) % mod + mod) % mod;
}
}
ll p(ll x,ll y) {
ll z = (x - 1) * m + y;
if(ma[z]) return ma[z];
return z;
}
ll cnt = 1,ans;
void solve(int x,int y) {
++cnt;
if(x == n && y == m) return;
int down = INF,right = INF;
if(x != n) down = FBI::main(p(x + 1,y));
if(y != m) right = FBI::main(p(x,y + 1));
if(down <= right) {
ans += cnt * down % mod;
ans %= mod;
solve(x + 1,y);
}
else {
ans += cnt * right % mod;
ans %= mod;
solve(x,y + 1);
}
return;
}
int main() {
n = read(),m = read(),Q = read(),mod = read(),C1 = read(),C2 = read();
for(int i = 1;i <= Q;++i) {
ll x = read(),y = read(),tx = x,ty = y;
if(ma[x]) tx = ma[x];
if(ma[y]) ty = ma[y];
ma[x] = ty;ma[y] = tx;
}
FBI::pre();
if(ma[1]) ans += FBI::main(ma[1]),ans %= mod;
else ans += FBI::main(1),ans %= mod;
solve(1,1);
cout<<ans;
return 0;
}

bzoj4490 随机数生成器Ⅱ加强版的更多相关文章

  1. bzoj4471 bzoj4490 随机数生成器Ⅱ

    Description 继NOI2014后,小H又发现了一种新的生成随机数的方法.首先,给定三个随机种子P,C1,C2(C1≤C2)生成一个序列{xi},{xi}满足对于任意的i≥0,满足以下递推式X ...

  2. 【原创】开源Math.NET基础数学类库使用(13)C#实现其他随机数生成器

                   本博客所有文章分类的总目录:[总目录]本博客博文总目录-实时更新  开源Math.NET基础数学类库使用总目录:[目录]开源Math.NET基础数学类库使用总目录 前言 ...

  3. 【BZOJ-3122】随机数生成器 BSGS

    3122: [Sdoi2013]随机数生成器 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1362  Solved: 531[Submit][Sta ...

  4. BZOJ-2875 随机数生成器 矩阵乘法快速幂+快速乘

    题目没给全,吃X了... 2875: [Noi2012]随机数生成器 Time Limit: 10 Sec Memory Limit: 512 MB Submit: 1479 Solved: 829 ...

  5. [BZOJ3671][UOJ#6][NOI2014]随机数生成器

    [BZOJ3671][UOJ#6][NOI2014]随机数生成器 试题描述 小H最近在研究随机算法.随机算法往往需要通过调用随机数生成函数(例如Pascal中的random和C/C++中的rand)来 ...

  6. NOI2014 随机数生成器

    随机数生成器 [问题描述] 小H最近在研究随机算法.随机算法往往需要通过调用随机数生成函数(例如Pascal中的random和C/C++中的rand)来获得随机性.事实上,随机数生成函数也并不是真正的 ...

  7. 【BZOJ 3122】 [Sdoi2013]随机数生成器 (BSGS)

    3122: [Sdoi2013]随机数生成器 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1442  Solved: 552 Description ...

  8. Linux下对拍脚本与随机数生成器

    对拍脚本 新建一个文档 check.sh 作为对拍脚本. #!/bin/bash while(true)do #死循环 ./data > .in #运行数据生成器,将数据输出到1.in ./st ...

  9. 矩阵(快速幂):COGS 963. [NOI2012] 随机数生成器

    963. [NOI2012] 随机数生成器 ★★   输入文件:randoma.in   输出文件:randoma.out   简单对比 时间限制:1 s   内存限制:128 MB [问题描述] 栋 ...

随机推荐

  1. pdf文件下载水印添加的中文与空格问题解决

    public static boolean waterMark(String inputFile, String outputFile, String waterMarkName)throws IOE ...

  2. defer 和 async 区别

    defer saync 共同点: script 标签属性, 控制脚本加载时间,解决script下载阻塞的问题. 区别: defer:推推推荐! 异步加载,所有元素解析完执行. async: 异步加载, ...

  3. Python查找指定文件

    在当前目录以及当前目录的所有子目录下查找文件名包含指定字符串的文件,并打印出相对路径: import os testfiles = [] testfilepaths = [] L = len(os.p ...

  4. scrapy安装失败:error:Microsoft Visual C++ 14.0 is reuired.及同类型安装问题解决办法

    今天在安装scrapy的时候(pip install Scrapy),出现了如下错误: building 'twisted.test.raiser' extensionerror: Microsoft ...

  5. Java注解原理

    1. @interface不是接口是注解类,使用@interface自定义注解时,自动继承了java.lang.annotation.Annotation接口,由编译程序自动完成其他细节 2. @in ...

  6. CSAPP:第十章 系统级I/O

    CSAPP:第十章 系统级I/O 10.1 unix I/O10.2 文件10.3 读取文件元数据10.4 读取目录内容10.5 共享文件10.6 我们该使用哪些I/O函数? 10.1 unix I/ ...

  7. gdb cheat sheet

    0x01 控制流 r run,运行程序. r < a.txt   run,重定向输入 si   step instruction 进入函数 ni      next instruction 下一 ...

  8. 一个简单的以太坊合约让imtoken支持多签

    熟悉比特币和以太坊的人应该都知道,在比特币中有2种类型的地址,1开头的是P2PKH,就是个人地址,3开头的是P2SH,一般是一个多签地址.所以在原生上比特币就支持多签.多签的一个优势就是可以多方对一笔 ...

  9. 爬取5K分辨率超清唯美壁纸

    目录 爬取5K分辨率超清唯美壁纸 简介 编写思路 使用教程 演示图片 完整源代码 @ 爬取5K分辨率超清唯美壁纸 简介 壁纸的选择其实很大程度上能看出电脑主人的内心世界,有的人喜欢风景,有的人喜欢星空 ...

  10. .NET 跨平台RPC框架DotNettyRPC

    DotNettyRPC 1.简介 DotNettyRPC是一个基于DotNetty的跨平台RPC框架,支持.NET45以及.NET Standard2.0 2.产生背景 传统.NET开发中遇到远程调用 ...