HDU - 6253 Knightmare (打表+拉格朗日插值)
题意:一个马在无限大的棋盘中跳,问跳n步能跳到多少个不同的格子。
首先写个打表程序打一下n比较小的时候的表:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=+,mod=;
const int dx[]= {-,-,,,,,-,-};
const int dy[]= {-,-,-,-,,,,};
typedef pair<int,int> P;
set<P> st[];
int n=,a[N];
int main() {
st[].insert({,});
for(int i=; i<n; ++i) {
for(P p:st[i&]) {
st[i&^].insert(p);
for(int j=; j<; ++j)st[i&^].insert({p.first+dx[j],p.second+dy[j]});
}
a[i]=st[i&].size();
}
for(int i=; i<n; ++i)printf("%d ",a[i]);
return ;
}
打印结果:
把元素差分两次后,成了这个亚子:
发现了什么?当n比较大的时候,经过二次差分后的数组的每一项都是28!因此可以猜测答案是一个关于n的二次多项式,现在要做的是把这个多项式推出来。
手算当然可以,但有没有一个可以不用动脑子就算出来的代码吗?答案是肯定的。拉格朗日插值大法好!
核心代码:(只需要写三个函数,前两个函数的作用是封装多项式的加法和乘法,第三个函数的作用是插值)
typedef double db;
typedef vector<db> Poly;
Poly operator*(Poly a,Poly b) {
Poly c;
c.resize(a.size()+b.size()-);
for(int i=; i<a.size(); ++i)
for(int j=; j<b.size(); ++j)c[i+j]+=a[i]*b[j];
return c;
}
Poly operator+(Poly a,Poly b) {
Poly c;
c.resize(max(a.size(),b.size()));
for(int i=; i<c.size(); ++i) {
if(i<a.size())c[i]+=a[i];
if(i<b.size())c[i]+=b[i];
}
return c;
}
Poly Lagrange(Poly X,Poly Y) {
Poly c;
int n=X.size();
for(int i=; i<n; ++i) {
Poly x({});
for(int j=; j<n; ++j)if(j!=i) {
x=x*Poly({-X[j],});
x=x*Poly({1.0/(X[i]-X[j])});
}
c=c+x*Poly({Y[i]});
}
return c;
}
这样一来,只要输入X向量和Y向量,就能直接求出原多项式了,非常方便。比如输入如下两个向量:
Poly a({,,}),b({,,});
Poly c=Lagrange(a,b);
for(db x:c)printf("%f ",x);
输出的结果为
1.000000 -1.000000 1.000000
也就是说,三个点$(1,2),(2,3),(3,7)$所确定的多项式为$f(x)=x^2-x+1$
现在我们在打印的结果中任取三个点比如$(10,1345),(11,1633),(12,1949)$,得到的结果为:
5.000000 -6.000000 14.000000
即答案关于n的多项式为$f(n)=14n^2-6n+5$。当n比较大时的答案就可以通过这个式子算出来了,n比较小的时候直接输出结果即可。最终提交上去的代码应该是这个亚子:
#include<bits/stdc++.h>
using namespace std;
typedef unsigned long long ll;
const int N=+,inf=0x3f3f3f3f;
const int a[]= {,,,,,,,,,,};
int ka,n;
int main() {
int T;
for(scanf("%d",&T); T--;) {
printf("Case #%d: ",++ka);
scanf("%d",&n);
if(n<=)printf("%d\n",a[n]);
else printf("%llu\n",-(ll)*n+(ll)*n*n);
}
return ;
}
注意要用unsigned long long,OK了~
ps:如果对精度要求高的话,也可以用分数版的:
struct Frac {
int x,y;
Frac(int _x=,int _y=):x(_x),y(_y) {
int g=__gcd(x,y);
x/=g,y/=g;
if(y<)x=-x,y=-y;
}
Frac operator-() {return Frac(-x,y);}
Frac operator+(Frac b) {return Frac(x*b.y+y*b.x,y*b.y);}
Frac operator+=(Frac b) {return *this=(*this)+b;}
Frac operator-(Frac b) {return Frac(x*b.y-y*b.x,y*b.y);}
Frac operator-=(Frac b) {return *this=(*this)-b;}
Frac operator*(Frac b) {return Frac(x*b.x,y*b.y);}
Frac operator*=(Frac b) {return *this=(*this)*b;}
Frac operator/(Frac b) {return Frac(x*b.y,y*b.x);}
Frac operator/=(Frac b) {return *this=(*this)/b;}
};
typedef Frac db;
typedef vector<db> Poly;
Poly operator*(Poly a,Poly b) {
Poly c;
c.resize(a.size()+b.size()-);
for(int i=; i<a.size(); ++i)
for(int j=; j<b.size(); ++j)c[i+j]+=a[i]*b[j];
return c;
}
Poly operator+(Poly a,Poly b) {
Poly c;
c.resize(max(a.size(),b.size()));
for(int i=; i<c.size(); ++i) {
if(i<a.size())c[i]+=a[i];
if(i<b.size())c[i]+=b[i];
}
return c;
}
Poly Lagrange(Poly X,Poly Y) {
Poly c;
int n=X.size();
for(int i=; i<n; ++i) {
Poly x({Frac()});
for(int j=; j<n; ++j)if(j!=i) {
x=x*Poly({-X[j],Frac()});
x=x*Poly({Frac()/(X[i]-X[j])});
}
c=c+x*Poly({Y[i]});
}
return c;
}
HDU - 6253 Knightmare (打表+拉格朗日插值)的更多相关文章
- hdu 6253 (bfs打表)
链接:http://acm.hdu.edu.cn/showproblem.php?pid=6253 题意: 马可以往一个方向走两步,然后转个弯走一步,这样算一次动作,求问马n次动作后,能到达多少个点, ...
- 【BZOJ2655】calc DP 数学 拉格朗日插值
题目大意 一个序列\(a_1,\ldots,a_n\)是合法的,当且仅当: 长度为给定的\(n\). \(a_1,\ldots,a_n\)都是\([1,m]\)中的整数. \(a_1, ...
- BZOJ.2655.calc(DP/容斥 拉格朗日插值)
BZOJ 洛谷 待补.刚刚政治会考完来把它补上了2333.考数学去了. DP: 首先把无序化成有序,选严格递增的数,最后乘个\(n!\). 然后容易想到令\(f_{i,j}\)表示到第\(i\)个数, ...
- BZOJ.3453.tyvj 1858 XLkxc(拉格朗日插值)
BZOJ 题意即求\[\sum_{i=0}^n\sum_{j=1}^{a+id}\sum_{x=1}^jx^k\] 我们知道最后一个\(\sum\)是自然数幂和,设\(f(n)=\sum_{x=1}^ ...
- fold算法(拉格朗日插值)
如果打表发现某个数列: 差分有限次之后全为0 例如: 2017新疆乌鲁木齐ICPC现场赛D题 ,,,,,,,,,,…… [2018江苏南京ICPC现场赛也有这样的题目] 那么可以使用以下黑科技计算出第 ...
- 【BZOJ】2655: calc 动态规划+拉格朗日插值
[题意]一个序列$a_1,...,a_n$合法当且仅当它们都是[1,A]中的数字且互不相同,一个序列的价值定义为数字的乘积,求所有序列的价值和.n<=500,A<=10^9,n+1< ...
- jzoj5683. 【GDSOI2018模拟4.22】Prime (Min_25筛+拉格朗日插值+主席树)
题面 \(n\leq 10^{12},k\leq 100\) 题解 一眼就是一个\(Min\_25\)筛+拉格朗日插值优化,然而打完之后交上去发现只有\(60\)分 神\(tm\)还要用主席树优化-- ...
- BZOJ 2655: calc(拉格朗日插值)
传送门 解题思路 首先比较容易能想到\(dp\),设\(f[i][j]\)表示前\(j\)个数,每个数\(<=i\)的答案,那么有转移方程:\(f[i][j]=f[i-1][j-1]*i*j+f ...
- Educational Codeforces Round 7 F - The Sum of the k-th Powers 拉格朗日插值
The Sum of the k-th Powers There are well-known formulas: , , . Also mathematicians found similar fo ...
随机推荐
- Object.assign()的用法 -- 用于将所有可枚举属性的值从一个或多个源对象复制到目标对象,返回目标对象
语法: Object.assign(target, …sources) target: 目标对象,sources: 源对象用于将所有可枚举属性的值从一个或多个源对象复制到目标对象.它将返回目标对象. ...
- 模块的概念、模块的导入方式【IMPORT 模块名、FROM 模块 IMOPRT 功能】、模块的搜索路径、链式导入&循环导入
今日内容 1. 模块:模块的概念 2.导入的方式:import from import 3. 环境变量:sys.path 4. 导入模块的顺序 5. 循环导入:模块间互相导入 模块 常见的四种模块: ...
- SQL注入-预防
输入验证: 检查用户输入的合法性,确信输入的内容只包含合法的数据.数据检查应当在客户端和服务器端都执行服务器端验证,是为了弥补客户端验证机制脆弱的安全性. 输入验证最好使用“白名单”校验的方式. 输入 ...
- C语言 俄罗斯方块的实现1 全局变量
目录 全局变量 程序的模块化之MVC 关于俄罗斯方块的代码实现要点 使用数组表示背景和方块 方块表示及其初始化 要让游戏动起来 方块自动下落 全局变量 简而言之,定义在函数外的变量,就是全局变量. 所 ...
- 关于js查找和筛选和循环的几种方式
find(); find() 方法返回通过测试(函数内判断)的数组的第一个元素的值. find() 方法为数组中的每个元素都调用一次函数执行: 当数组中的元素在测试条件时返回 true 时, find ...
- ES6简单初识
ES常用命令介绍 函数的Rest参数和扩展 Promise使用 Module.exports和ES6 import/export的使用 promise使用 promise 为了解决callback嵌套 ...
- 计算机和python
计算机基础知识 CPU 人类的大脑 运算和处理问题 内存 临时存储数据 断电就消失了 硬盘 永久 存储数据 操作系统是一个(特殊)的程序,调度硬件和软件之间的数据交互 python的应用和历史 IT, ...
- SpringMVC实现全局异常处理器 (转)
出处: SpringMVC实现全局异常处理器 我们知道,系统中异常包括:编译时异常和运行时异常RuntimeException,前者通过捕获异常从而获取异常信息,后者主要通过规范代码开发.测试通过手 ...
- hbase启动后HMaster几秒后死掉
通过 http://s128:16010 无法访问Hbase Web端 查看master日志,有报错: 2019-08-30 16:27:35,137 ERROR [master/s128:16000 ...
- 链接校验——是否是协议http://或https://开头的
if(str.substr(0,7)!="http://" && str.substr(0,7)!="https://"){ return 'y ...