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 ...
随机推荐
- yum安装etcd集群
前一篇文章介绍了如何yum安装简单的kubernetes集群,其中etcd是单点部署.本篇我们来搭建etcd集群,方便日后搭建kubernetes HA集群架构. 1,环境配置说明 etcd1 ...
- Vuex的认识和简单应用(一)
一.vuex是一个专为vue.js应用程序开发的状态管理模式. 应用场景:1.多个视图依赖于同一个状态2.来自不同视图的行为需要变更同一个状态此时,我们可以把组件的共享状态抽取出来,以一个全局单例模式 ...
- Emgu 学习笔记(8)之膨胀腐蚀
static void Main(String[] args) { Mat img = CvInvoke.Imread(); Mat d = new Mat(); Mat e = new Mat(); ...
- synchronized(三) 锁的膨胀过程(锁的升级过程)深入剖析
警告⚠️:本文耗时很长,先做好心理准备................哈哈哈 本篇我们讲通过大量实例代码及hotspot源码分析偏向锁(批量重偏向.批量撤销).轻量级锁.重量级锁及锁的膨胀过程(也就是 ...
- [Python3] 033 异常
目录 异常 1. 简介 2. 异常的分类 3. 出现异常小例子 例子 4. 异常处理 5. 解决异常小例子 5.1 例子1 5.2 例子2 5.3 例子3 5.4 例子4 6. 手动引发异常 6.1 ...
- spring依赖注入三种方式
一.构造器注入 构造器注入是在程序中实现构造器,可以注入任意类型,如自定义类,集合,String等,注:构造器所有有final修饰的变量都必须在构造方法中注入. 二.设值注入(setter方式注入) ...
- Java 中的动态代理
一.概述 1. 什么是代理 我们大家都知道微商代理,简单地说就是代替厂家卖商品,厂家“委托”代理为其销售商品.关于微商代理,首先我们从他们那里买东西时通常不知道背后的厂家究竟是谁,也就是说,“委托者” ...
- swift MT报文解析处理
swift 官方资料:https://www2.swift.com/knowledgecentre/publications/us5mc_20180720/2.0?topic=alec.htm#gen ...
- Codeforces 817+818(A~C)
(点击题目即可查看原题) 817A Treasure Hunt 题意:给出起点和终点,每次移动只能从 (a,b)移动至(a+x,b+y) , (a+x,b-y) , (a-x,b+y) , (a-x, ...
- Centos8 安装ifconfig(net-tools.x86_64)
情况: yum search net-tools.x86_64 没有找到结果 解决: 1.yum search net-tools 2. yum install -y net-tools.x86_64 ...