HDU-2802-F(N)
看到这题讨论版里有说用公式的有说用循环节的,但是个人觉得这两种方法都不靠谱,比赛场上做这种题能直接推出公式需要很强数学功底,而循环节的方法如果循环节比较大就不太好发现了。这种已知通项公式的题还是用矩阵快速幂比较通用,但同是矩阵快速幂,对于这题,也有很大的差异;
注:memmove这个函数可能不太常见,但还是比较好用的,可以用较低的时间复杂度完成数组的拷贝
- 方法一
Time Limit Exceeded 2802 1000MS 1348K 1734 B G++ #include "bits/stdc++.h"
using namespace std;
const int MOD = ;
/*
{f(n - 1), f(n - 2), n ^ 3, (n - 1) ^ 3, n ^ 2, n, 1}
乘MAT得到
{f(n), f(n - 1), (n + 1) ^ 3, n ^ 3, (n + 1) ^ 2, n + 1, 1}
*/
const int MAT[][] = {
{, , , -, , , },
{, , , , , , },
{, , , , , , },
{, , , , , , },
{, , , , , , },
{, , , , , , },
{, , , , , , }
};
const int TABLE[] = {, , , , , , };
struct Mat {
int mat[][];
Mat() {
memset(mat, , sizeof(mat));
}
friend Mat operator * (Mat n, Mat m) {
Mat res;
for (int k = ; k < ; k++)
for (int i = ; i < ; i++)
for (int j = ; j < ; j++) {
res.mat[i][j] += n.mat[i][k] * m.mat[k][j];
// 因为当n >=0 时 (n + 1) ^ 3 一定大于 n ^ 3,所以要保证结果是正数;
res.mat[i][j] = (res.mat[i][j] % MOD + MOD) % MOD;
}
return res;
}
} m;
Mat mat_pow(Mat n, int k) {
Mat res;
for (int i = ; i < ; i++) {
res.mat[i][i] = ;
}
while (k) {
if (k & ) {
res = res * n;
}
n = n * n;
k >>= ;
}
return res;
}
int main() {
int n;
while (scanf("%d", &n) && n) {
if (n == ) {
puts("");
continue;
}
if (n == ) {
puts("");
continue;
}
memmove(m.mat, MAT, sizeof(m.mat));
m = mat_pow(m, n - );
int res = ;
for (int i = ; i < ; i++) {
res = (res + m.mat[][i] * TABLE[i]) % MOD;
}
printf("%d\n", res);
}
return ;
}这是拿到题直接把递推式拿来套的解法,7层矩阵,超时。于是想到n ^ 3 - (n - 1) ^ 3 = (n - 1) ^ 3 + 3 * (n - 1) ^ 2 + 3 * (n - 1) + 1 - (n - 1) ^ 3;可以抵消(n - 1) ^ 3;
方法二
Accepted 2802 889MS 1384K 1462 B G++ #include "bits/stdc++.h"
using namespace std;
const int MOD = ;
/*
{f(n - 1), f(n - 2), n ^ 2, n, 1}
乘MAT得到
{f(n), f(n - 1), (n + 1) ^ 2, n + 1, 1}
*/
const int MAT[][] = {
{, , , , },
{, , , , },
{, , , , },
{, , , , },
{, , , , }
};
const int TABLE[] = {, , , , };
struct Mat {
int mat[][];
Mat() {
memset(mat, , sizeof(mat));
}
friend Mat operator * (Mat n, Mat m) {
Mat res;
for (int k = ; k < ; k++)
for (int i = ; i < ; i++)
for (int j = ; j < ; j++)
res.mat[i][j] = (res.mat[i][j] + n.mat[i][k] * m.mat[k][j]) % MOD;
return res;
}
} m;
Mat mat_pow(Mat n, int k) {
Mat res;
for (int i = ; i < ; i++) {
res.mat[i][i] = ;
}
while (k) {
if (k & ) {
res = res * n;
}
n = n * n;
k >>= ;
}
return res;
}
int main() {
int n;
while (scanf("%d", &n) && n) {
if (n == ) {
puts("");
continue;
}
if (n == ) {
puts("");
continue;
}
memmove(m.mat, MAT, sizeof(m.mat));
m = mat_pow(m, n - );
int res = ;
for (int i = ; i < ; i++) {
res = (res + m.mat[][i] * TABLE[i]) % MOD;
}
printf("%d\n", res);
}
return ;
}降到5层矩阵之后能AC掉这题了,但是这个矩阵还不是最好的。这个代码的效率还是不高。
- 方法三
Accepted 2802 483MS 1392K 1551 B G++ #include "bits/stdc++.h"
using namespace std;
const int MOD = ;
/*
{f(n - 2), (n + 1) ^ 2, (n + 1), 1}
乘MAT得到
{f(n), (n + 3) ^ 2, n + 3, 1}
*/
const int MAT[][] = {
{, , , },
{, , , },
{, , , },
{, , , }
};
const int TABLE1[] = {, , , };
const int TABLE2[] = {, , , };
struct Mat {
int mat[][];
Mat() {
memset(mat, , sizeof(mat));
}
friend Mat operator * (Mat n, Mat m) {
Mat res;
for (int k = ; k < ; k++)
for (int i = ; i < ; i++)
for (int j = ; j < ; j++)
res.mat[i][j] = (res.mat[i][j] + n.mat[i][k] * m.mat[k][j]) % MOD;
return res;
}
} m;
Mat mat_pow(Mat n, int k) {
Mat res;
for (int i = ; i < ; i++) {
res.mat[i][i] = ;
}
while (k) {
if (k & ) {
res = res * n;
}
n = n * n;
k >>= ;
}
return res;
}
int main() {
int n;
while (scanf("%d", &n) && n) {
if (n == ) {
puts("");
continue;
}
if (n == ) {
puts("");
continue;
}
memmove(m.mat, MAT, sizeof(m.mat));
m = mat_pow(m, n - >> );
int res = ;
/*
假设重定义两个函数,a(n) = f(2 * n - 1), b(n) = f(2 * n);
if (n & 1) 求得a((n - 1) >> 1)即为 f(n)
else 求得b((n - 1) >> 1) 即为f(n)
*/
if (n & ) {
for (int i = ; i < ; i++) {
res = (res + m.mat[][i] * TABLE1[i]) % MOD;
}
} else {
for (int i = ; i < ; i++) {
res = (res + m.mat[][i] * TABLE2[i]) % MOD;
}
}
printf("%d\n", res);
}
return ;
}递推式是从f(n)直接到f(n + 2)的,所以相当于把f拆成两个函数分开讨论,只用4层矩阵就够了。对于矩阵快速幂,4层应该是最少的了。如果还要再快,那就只能采取循环节或公式的方式了。
- 方法四(来自讨论版,代码省略)
这题的循环节是4018(正好是MOD的两倍,不知道是不是巧合)。
- 方法五(来自讨论版,代码省略)
n为奇数 (n+1)(n+1)(2n-1)/4;
n为偶数 n*n*(2n+3)/4
HDU-2802-F(N)的更多相关文章
- HDU 2802 F(N)(简单题,找循环解)
题目链接 F(N) Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Sub ...
- HDU - 2802 F(N) (周期)
题目链接:HDU 2009-4 Programming Contest 分析:具有一定的周期性——4018处理下就可以A了 Sample Input Sample Output AC代码: #incl ...
- HDU 2802 F(N) 数论+打表
题目大意:f[n]-n^3=f[n-2]-(n-1)^3 (n >=3),f[1]=1,f[2]=7,求f[n]. 题目思路:将n^3移到到等式右边化简的到:f[n]=f[n-2]+3n*(n- ...
- 数学--数论--HDU 2802 F(N) 公式推导或矩阵快速幂
Giving the N, can you tell me the answer of F(N)? Input Each test case contains a single integer N(1 ...
- 【数位DP】 HDU 4734 F(x)
原题直通车:HDU 4734 F(x) 题意:F(x) = An * 2n-1 + An-1 * 2n-2 + ... + A2 * 2 + A1 * 1, 求0.....B中F[x]<=F[A ...
- HDU 4734 F(x) 2013 ACM/ICPC 成都网络赛
传送门:http://acm.hdu.edu.cn/showproblem.php?pid=4734 数位DP. 用dp[i][j][k] 表示第i位用j时f(x)=k的时候的个数,然后需要预处理下小 ...
- HDU 4734 - F(x) - [数位DP][memset优化]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4734 Time Limit: 1000/500 MS (Java/Others) Memory Lim ...
- HDU 1937 F - Finding Seats 枚举
F - Finding Seats Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u S ...
- hdu 4734 F(x)(数位dp+优化)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4734 题意:我们定义十进制数x的权值为f(x) = a(n)*2^(n-1)+a(n-1)*2(n-2 ...
- E - Tunnel Warfare HDU - 1540 F - Hotel G - 约会安排 HDU - 4553 区间合并
E - Tunnel Warfare HDU - 1540 对这个题目的思考:首先我们已经意识到这个是一个线段树,要利用线段树来解决问题,但是怎么解决呢,这个摧毁和重建的操作都很简单,但是这个查询怎么 ...
随机推荐
- 2. 现代 javascript 新语法 及 对象专题
let , const 和 var javascript 里面的作用域 一个大括号 是一个作用域 { } var 会 在局部作用定义 被定义时 会提升作用域 如 if 的 {} 就属于 局部作用域 ...
- 1. laravel 学习 环境搭建
1. 项目环境 vagrant + laradock (因为 自己手动搭建环境太麻烦了 自己弄了一下 感觉还是有些漏洞 所以采用 laradock) 2. Vagrantfile 备注 : box ...
- LeetCode——48. 旋转图像
给定一个 n × n 的二维矩阵表示一个图像. 将图像顺时针旋转 90 度. 说明: 你必须在原地旋转图像,这意味着你需要直接修改输入的二维矩阵.请不要使用另一个矩阵来旋转图像. 示例 1: 给定 m ...
- long型长整数字在前端页面显示异常及其解决方法
文章目录 1.引子 2.解决问题 (1)初试EL表达式取long型数值 (2)再探EL表达式取字符串格式long型数值 (3)最后一试---给EL表达式加引号 3.总结 1.引子 在做项目中,发现了一 ...
- 复杂json解析方式[GsonFormat]
针对开发人员来讲,善于用工具,事半功倍. 干货: 1.IntelliJ IDEA 通过GsonFormat插件将JSONObject格式的String 解析成实体 插件地址:https://plugi ...
- Centos7.6环境中安装zabbix3.4
官网链接:https://www.zabbix.com/documentation/3.4/zh/manual/installation/install_from_packages 部署环境 虚拟机服 ...
- rabbitmq安装(linux)遇到 很多坑
1.下载erlang官网地址 http://www.erlang.org/download 挑选合适的版本 然后 建议20.3运行命令 wget http://erlang.org/download/ ...
- xcode6添加pch文件
pch文件 定义:该文件中定义的内容为全局变量,可供所有类进行调用 例子:在pch文件中定义ios版本
- VMware-workstation虚拟机安装及配置
目录 安装准备 开始安装 设置虚拟机文件默认位置 安装准备 系统环境:Windows10 专业版 软件:VMware-workstation-full-14.0.0.24051.exe 秘钥:FF31 ...
- 关于jQuery中toggle参数callback函数提前执行问题
通过 jQuery,您可以使用 toggle() 方法来切换 hide() 和 show() 方法. 显示被隐藏的元素,并隐藏已显示的元素: $(selector).toggle(speed,call ...