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 ...
随机推荐
- php 通过mysqli 操作数据库mysql
目录 php mysqli 操作数据库 连接数据库 通过mysqli 创建数据库 通过mysqi 创建数据表 通过mysqli向数据表中插入信息 通过mysqli 读取数据 where语句的应用 通过 ...
- Python面试-websocket及web框架
一.Websocket 1. websocket概念 在讲websocket之前,我们先来看看ajax轮询和long poll的实现机制. A. ajax轮询 ajax轮询的原理非常简单,让浏览器隔 ...
- CISCO路由器WAN口动态ISP配置
Building configuration... version 15.0 service timestamps debug datetime msec service timestamps ...
- Ubuntu下c程序运行原理
运行环境: 1.Vitural box下安装Ubuntu虚拟机 2.编译运行工具:gcc 3.编辑器:vim 主要过程: 1.利用vim编辑hello.c 2.编译和执行 (1)预处理阶段:使用 -E ...
- 解决Wamp的 Error D:\wamp or PHP path 错误
之前早早就用了wamp,发现还是挺好用的,就是刚开始改端口号之类的配置有点麻烦,不过还是一一解决了. 就在昨天安装了 composer . 突然发现wamp 有一个错 “Error D:\wamp o ...
- (转)Jquery+Ajax实现Select动态定数据
解决思路: 在数据库中建立类型字典式表.将下拉框需要添加的项,在数据库表里中文.英文名称对应起来. 下拉框动态绑定数据库表中需要字段. <div id="bgDiv" sty ...
- SolidWorks学习笔记1
鼠标 修改缩放方向 点击工具->选项->视图,点击第一条,翻转鼠标滚轮缩放方向. 平移:Ctrl+ 中键 或者右键空白处 菜单选择平移 缩放:Shift+中键 或者右键空白处 菜单选择放大 ...
- Linux动态链接之GOT与PLT
转载于:http://www.cnblogs.com/xingyun/archive/2011/12/10/2283149.html 我们知道函数名就是一个内存地址,这个地址指向函数的入口.调用函 ...
- Centos8 重启网卡方法
问题情况: 1.虚机centos8 修改为静态ip后,由于网卡网段变更,无法上网 2.最小化安装,没有ifconfig 3.firewalld,selinux关闭 4.ping 不通物理机 根本原因: ...
- [BZOJ 2002] [HNOI2010]弹飞绵羊(Link Cut Tree)
[BZOJ 2002] [HNOI2010]弹飞绵羊(Link Cut Tree) 题面 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一 ...