很不错的一道题,很让我见识到了差分序列的运用的神奇之处。。一下是从北邮BBS看到的题解,写得很清楚。。这边就直接转过来。

uRLhttp://bbs.byr.cn/#!article/ACM_ICPC/33403

**********************************************************************

其实是挺简单的一个题目,希望大家都看看 
   
给出一个多项式p(x)=a[n]*x^n+...+a[1]*x+a[0],并给初始x值L,和数m,k,求出从x=L,L+1,...L+k-1的 p(x)的最后m个数字的平方和(有点绕),即,若p(x)=34,则输出3*3+4*4=25,x的值从L到L+k-1.且初始值l和多项式的常数 a[i]可能很大,最大到10^1000.多项式最高次最大为10,总时限10秒,case time limit 两秒 
   
最初看到这个题目以为是纯高精,敲了个java上去超时,自己写裸的高精,超时,写FFT乘法,超时(=_=!!),然后以为有递推关系,用二项式定理搞了个递推,再加上自己写了个100000000进制的高精,勉强把复杂度降到10的8次方,卡了半天常数过掉了。晚上仔细翻了下书,其实有更方便的方法。 
   
先简单科普下差分序列,大家应该都在组合数学课上见这个东西 
如果有序列 
a[1][1] a[1][2] a[1][3] ... a[1][n] 
则有 
a[i][j]=a[i-1][j+1]-a[i-1][j] 
   
比如这个差分表: 
1 4   13 34 73 
3 9   21 39 
6 12 18 
6 6 

除了第一行外,它的每一项是它上面一行的相邻两个数之差 
   
若一个差分表的第一行是多项式p(x) p(x+1) p(x+2)...且多项式的次数为n,则这个差分表有下面的性质可以让我们利用: 
1.差分表在第n+1行后的所有元素均为0,第n行为一个常数. 
    简要说下证明思路,设第i阶差分序列为p[i](x),则第i+1阶序列为p[i+1](x)=p[i](x+1)-p[i](x),这也是个确定的多项式,且次数减一.递推到n阶的时候次数为0,即为一个常数.可知n+1行以后均为0 
2.若知道差分表的第一列的前n+1项,则可以确定这个多项式. 
    很明显,知道这些项后,可以逆推出第一行的前n+1项,通过解线性方程可以确定各项系数。 
比如前面给的那个差分表,对应的多项式是p(x)=x^3+2*x+1 
   
回到题目,到这里其实应该很容易看出,只要知道差分表的前n+1列,那么根据a[i][j]=a[i-1][j]+a[i-1][j-1],以后的所有元素都可以推出来。而计算这前n+1列,需要p(L),p(L+1)...p(L+n),因为n最多为10,所以可以很快用最挫的方法暴力求出来。 
而最初始的表建好后,对每一项p(x),可以从下往上递推a[i][j]=a[i-1][j]+a[i-1][j-1],需要实现的只是几个基本高精计算的函数,最后把需要的东西求出来即可。 
   
建初始表的复杂度最大为O(10*10*1000+10*10*1000)~O(10^5),之后递推的复杂度为O(1000*10*1000)~O(10^7),对于每个case两秒的时限已经基本足够了,刚才提交的时候所有case运行时间在两秒左右:-) 
   
话说这是有屎以来卡得我最久的一道题了...orz orz...  
********************************************************************************

*********************************************************************************

这里补充说一下,第i阶-->第i + 1阶为什么多项式会降阶

假设:p(x) = an*x^n + an-1 * x^(n-1).......a1*x + a0

对于第一阶: p(x)        p(x+1)     p(x+2)     p(x+3)...

对于第二阶:p(x+1)-p(x)   p(x+2)-p(x+1).....

设y = x + 1, 则会有:p(y)- p(x) = an*(y^n - x^n) + an-1 * (y ^ (n -1)  - x ^ (n - 1)))...........a1*(y - x) + 1 *(a0- a0) = an*(y^n - x^n) + an-1 * (y ^ (n -1)  - x ^ (n - 1)))........... + a2 * (y ^ 2 - x ^ 2)  + a1

那么,这样一来,最后一项便消掉(因为a0 - a0), 所以a1就变成了常数。。

由此可知,每多一阶,多项式便降一阶(这样说好像不大准确,不过大概可以这样理解)

当然,最后一行为什么都是相等的常数,而且每一行都的系数的绝对值都符合杨辉三角(指的是p(x),p(x+1)...之前的系数)。

我太弱了,到现在还没理解,也不会证明,(跪求大神指教)

但是,把表打出来你会发现一个规律,当 最高次为x^1,x^2, x^3,...是,最后一行常数分别为1!,2!,3!.....

当然,这里是认为最高项系数为1的情况,当系数不为1,该常数还要乘以系数。。

不会java的渣渣只能写出这种code了。。

 /*
* Author: yzcstc
* Created Time: 2013/10/9 0:38:51
* File Name: poj2094.cpp
*/
#include<iostream>
#include<sstream>
#include<fstream>
#include<vector>
#include<list>
#include<deque>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<bitset>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
#include<utility>
#define M0(x) memset(x, 0, sizeof(x))
#define Inf 0x7fffffff
#define PB push_back
#define SZ(v) ((int)(v).size())
using namespace std;
int c[];
int n, k, m;
struct Biginteger{
int d[], sz;
void clr(){
for (int i = ; i <= sz; ++i)
d[i] = ;
sz = ;
}
void changenum(const char s[]){
sz = strlen(s);
for (int i = ; i <= sz; ++i)
d[i] = s[sz - i] -'';
}
void plus(const Biginteger & b){
sz = max(sz, b.sz);
if (sz > m) sz = m;
int x = ;
for (int i = ; i <= sz; ++i){
x = x + d[i] + b.d[i];
d[i] = x % ;
x /= ;
}
while (sz < m && x) d[++sz] = x % , x /= ;
}
void sub(const Biginteger & b){
sz = max(sz, b.sz);
if (sz > m) sz = m;
int x = ;
for (int i = ; i <= sz; ++i){
x = d[i] - b.d[i] - x;
d[i] = (x + ) % ;
if (x < ) x = ;
else x = ;
}
}
void multiply(const Biginteger & b){
for (int i = ; i <= sz + b.sz; ++i)
c[i] = ;
for (int i = ; i <= sz; ++i)
for (int j = ; j <= b.sz; ++j)
c[i + j - ] += d[i] * b.d[j];
int x = ;
sz += b.sz;
if (sz > m) sz = m;
for (int i = ; i <= sz; ++i){
x = x + c[i];
d[i] = x % ;
x /= ;
}
while (sz >= && d[sz] == ) --sz;
}
} a[], q[][], l, one, t; char s[]; void init(){
l.changenum(s);
for (int i = ; i <= n; ++i){
scanf("%s", &s);
a[i].changenum(s);
}
} void outans(const Biginteger & a){
int ans = ;
for (int i = ; i <= min(a.sz, m); ++i)
ans += a.d[i] * a.d[i];
printf("%d\n", ans);
} void solve(){
for (int i = ; i <= min(n, k); ++i){
t = a[];
for (int j = ; j <= n; ++j){
t.multiply(l);
t.plus(a[j]);
}
q[n][i] = t;
outans(t);
l.plus(one);
}
if (k > n){
for (int i = n - ; i >= ; --i)
for (int j = ; j <= i; ++j){
q[i][j] = q[i + ][j + ];
q[i][j].sub(q[i + ][j]);
}
for (int i = ; i <= n; ++i)
q[][i] = q[][];
int p = , rw1, rw2;
for (int i = n + ; i < k; ++i){
for (int j = ; j <= n; ++j){
rw1 = (j + p) % (n + );
rw2 = (j + p - ) % (n + );
q[j][rw1] = q[j][rw2];
q[j][rw1].plus(q[j - ][rw2]);
}
outans(q[n][rw1]);
l.plus(one);
++p;
}
}
} int main(){
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
one.sz = one.d[] = ;
while (scanf("%d%s%d%d", &n, &s, &k, &m) == ){
init();
solve();
}
fclose(stdin); fclose(stdout);
return ;
}

poj2094的更多相关文章

  1. 【POJ2094】【差分序列】Angry Teacher

    Description Mr. O'Cruel is teaching Math to ninth grade students. Students of course are very lazy, ...

随机推荐

  1. hdu (欧拉函数+容斥原理) GCD

    题目链接http://acm.hdu.edu.cn/showproblem.php?pid=1695 看了别人的方法才会做 参考博客http://blog.csdn.net/shiren_Bod/ar ...

  2. Startup.国外新锐公司及其技术Blog

    国外技术公司Tech/Engineering Blog 1. vimeo https://coderwall.com/team/vimeo http://blog.assembly.com/ 2. l ...

  3. svg 配合cesium使用

    ---恢复内容开始--- 1.svg简介 在 2003 年一月,SVG 1.1 被确立为 W3C 标准. 参与定义 SVG 的组织有:太阳微系统.Adobe.苹果公司.IBM 以及柯达. 与其他图像格 ...

  4. 1.3 Java中的标识符和关键字

    1.标识符 含义:标识符用于给程序中的类.变量.方法命名的符号. 组成:数字(0-9).字母(a-z)(A-Z).下划线(_).美元符号$. 命名规则:1.数字不能够作为命名符号的开头 2.不能够使用 ...

  5. BZOJ 3007 [SDOI2012]拯救小云公主 - 对偶图 + 并查集

    Solution 答案具有单调性, 显然可以二分答案. 有两个注意点 : 英雄是可以随便走的, 也就是不是网格图... 还有坐标不能小于$1$ QAQ 开始时英雄在左下角, 公主在右上角, 我们反过来 ...

  6. Python之路(第二十篇) subprocess模块

    一.subprocess模块 subprocess英文意思:子进程 那什么是进程呢? (一)关于进程的相关理论基础知识 进程是对正在运行程序的一个抽象,进程的概念起源于操作系统,是操作系统最核心的概念 ...

  7. 利用js代码:document.forms[0].approval.value='false',当点击 <input type="image"按钮向表单传递不同的参数。

    <form action="flow_myTaskList"> <input type="hidden" name="approva ...

  8. jdom解析xml

    这次把代码整理了一下,打包发上来了,程序中需要用到的jar包也一起打在里面了,有兴趣的朋友可以解压后直接导入的eclipse里运行! xml是一种广为使用的可扩展标记语言,java中解析xml的方式有 ...

  9. 【Web】前端裁剪图片,并上传到服务器(Jcrop+canvas)

    web网站中常常有的功能:上传头像.上传封面等:一般图片都有一定的比例限制,所以需要前端在上传图片时,进行裁剪,并把裁剪后的图片进行上传. 本例采用Jcrop插件实现裁剪效果,canvas裁剪图片,并 ...

  10. Java第15章笔记

    字符串的概述 1.什么是字符串:零个或多个字符组成的有限序列 2.如何使用字符串:(使用字符串分为两步)          1)定义并初始化字符串          2)使用字符,对字符串进行一些处理 ...