题目链接

题意:一个马在无限大的棋盘中跳,问跳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 (打表+拉格朗日插值)的更多相关文章

  1. hdu 6253 (bfs打表)

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=6253 题意: 马可以往一个方向走两步,然后转个弯走一步,这样算一次动作,求问马n次动作后,能到达多少个点, ...

  2. 【BZOJ2655】calc DP 数学 拉格朗日插值

    题目大意 ​ 一个序列\(a_1,\ldots,a_n\)是合法的,当且仅当: ​ 长度为给定的\(n\). ​ \(a_1,\ldots,a_n\)都是\([1,m]\)中的整数. ​ \(a_1, ...

  3. BZOJ.2655.calc(DP/容斥 拉格朗日插值)

    BZOJ 洛谷 待补.刚刚政治会考完来把它补上了2333.考数学去了. DP: 首先把无序化成有序,选严格递增的数,最后乘个\(n!\). 然后容易想到令\(f_{i,j}\)表示到第\(i\)个数, ...

  4. 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}^ ...

  5. fold算法(拉格朗日插值)

    如果打表发现某个数列: 差分有限次之后全为0 例如: 2017新疆乌鲁木齐ICPC现场赛D题 ,,,,,,,,,,…… [2018江苏南京ICPC现场赛也有这样的题目] 那么可以使用以下黑科技计算出第 ...

  6. 【BZOJ】2655: calc 动态规划+拉格朗日插值

    [题意]一个序列$a_1,...,a_n$合法当且仅当它们都是[1,A]中的数字且互不相同,一个序列的价值定义为数字的乘积,求所有序列的价值和.n<=500,A<=10^9,n+1< ...

  7. jzoj5683. 【GDSOI2018模拟4.22】Prime (Min_25筛+拉格朗日插值+主席树)

    题面 \(n\leq 10^{12},k\leq 100\) 题解 一眼就是一个\(Min\_25\)筛+拉格朗日插值优化,然而打完之后交上去发现只有\(60\)分 神\(tm\)还要用主席树优化-- ...

  8. BZOJ 2655: calc(拉格朗日插值)

    传送门 解题思路 首先比较容易能想到\(dp\),设\(f[i][j]\)表示前\(j\)个数,每个数\(<=i\)的答案,那么有转移方程:\(f[i][j]=f[i-1][j-1]*i*j+f ...

  9. 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 ...

随机推荐

  1. 【HANA系列】SAP HANA SQL获取某字符串的位置

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[HANA系列]SAP HANA SQL获取某字 ...

  2. 深入源码分析Spring中的构造器注入

    # 1. 示例 构造器注入类,分别有三个构造器,一个是无参构造器,一个是注入一个Bean的构造器,一个是注入两个Bean的构造器: public class ConstructorAutowiredT ...

  3. collections(python常用内建模块)

    文章来源:https://www.liaoxuefeng.com/wiki/897692888725344/973805065315456 collections collections是Python ...

  4. C++学习笔记-多态的实现原理

    深入了解多态的实现原理,有助于提高对于多态的认识 多态基础 多态的实现效果 多态:同样的调用语句有多种不同的表现形态 多态实现的三个条件 有继承.有virtual重写.有父类指针(引用)指向子类对象 ...

  5. Emgu 学习(4) 使用指针访问图像内存

    在原始图像最初的10行绘制一个颜色条 class Program { static void Main(String[] args) { Mat img = CvInvoke.Imread(@&quo ...

  6. flask_script

    Flask Script扩展提供向Flask插入外部脚本的功能,包括运行一个开发用的服务器,一个定制的Python shell,设置数据库的脚本,cronjobs,及其他运行在web应用之外的命令行任 ...

  7. Elasticsearch-布尔类型

    boolean类型用于存储文档中的true/false.例如:专辑类型中需要添加一个字段表示是否可以下载,如下 curl -XPUT 'localhost:9200/music/album/4' -d ...

  8. windows10专业版激活

    [1]右击我的电脑->属性,查看激活情况 [2]管理员身份打开CMD [2.1]如果不知道CMD是什么东西 [2.2]如果上面那个也找不到,直接按windows键(就是ctrl和alt中间那个键 ...

  9. # 关于设置AUTH_USER_MODEL出现的问题

    关于设置AUTH_USER_MODEL出现的问题 在运行的时候出现了一个bug: AttributeError: type object 'UserProfile' has no attribute ...

  10. 加快ALTER TABLE 操作速度

    mysql的alter table操作的性能对于大表来说是个大问题.mysql大部分修改表结构操作的方法都是用新的结构创建一个 新表,从旧表中查出数据插入新表,然后在删除旧表.这样的操作很耗费时间,而 ...