自然数幂之和

来源:互联网 发布:c语言最长升序片段 编辑:程序博客网 时间:2024/05/21 15:02

简单的说,问题就是:

不同的问题随着k的大小变化解法也要求相应的进化。

zoj A very easy task

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1864

相关数据: (0 <= n <= 1050, 1 <= k <= 100)

二项式展开:进一步得到:把n变成n-1,n-2,''',1:上式累加:
换元:
k不断减小,直到递归到k=1,那么S(n,1)=(n+1)n/2; 时间复杂度:O(n^2)
import java.util.*;import java.math.BigInteger;public class Main {static final int N=110;    static BigInteger []ans=new BigInteger [N];    static BigInteger [][] C=new BigInteger[N][N];    static void init(){    for(int i=1;i<N;i++){    C[i][0]=C[i][i]=BigInteger.ONE;    for(int j=1;j<i;j++){    C[i][j]=C[i-1][j-1].add(C[i-1][j]);    }    }    }    static BigInteger solve(BigInteger n,int k){    if(ans[k].compareTo(BigInteger.valueOf(-1))!=0){    return ans[k];    }    if(k==1){    ans[k]=(n.add(BigInteger.ONE)).multiply(n).divide(BigInteger.valueOf(2));        return ans[k];    }    BigInteger t=BigInteger.ONE,temp=BigInteger.ZERO;    for(int i=0;i<k+1;i++){    t=t.multiply(n.add(BigInteger.ONE));    }    t=t.subtract(n.add(BigInteger.ONE));    for(int i=1;i<k;i++){    temp=temp.add(C[k+1][k+1-i].multiply(solve(n,i)));    }    t=t.subtract(temp);    ans[k]=t.divide(BigInteger.valueOf(k+1));    return ans[k];    }public static void main(String[] args) {init();BigInteger n;int k;Scanner cin=new Scanner (System.in);while(cin.hasNext()){n=cin.nextBigInteger();k=cin.nextInt();for(int i=0;i<N;i++){ans[i]=BigInteger.valueOf(-1);}System.out.println(solve(n,k));}}}

51nod 1228 序列求和
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1228
相关数据:(1 <= N <= 10^18, 1 <= K <= 2000)
T(n) = n^k,S(n) = T(1) + T(2) + ...... T(n)。给出n和k,求S(n)。
例如k = 2,n = 5,S(n) = 1^2 + 2^2 + 3^2 + 4^2 + 5^2 = 55。
由于结果很大,输出S(n) Mod 1000000007的结果即可。
分析:有5000case,自然数幂之和的普通解法O(k^2),故另辟蹊径。借助ACdreamer大神的思路,该问题和伯努利数联系。有这样的等式:
顺便回忆了一下逆元的相关知识,万能的求解,这里需要K=1-->2000,k+1 mod 1000000007的逆,可以使用递推逆元的方法预处理:
相关证明:http://blog.csdn.net/acdreamers/article/details/8220787
组合数C(n,m)同样预处理。
最后的伯努利:
mod操作,小心又小心,不要少加%mod。
import java.util.*;public class Main { static final int N=2005,mod=1000000007;    static long [][]C=new long [N][N]; static long []inv=new long [N],B=new long [N],nadd1=new long [N];    static void initC(){  C[0][0]=1;  for(int i=1;i<N;i++){   C[i][0]=C[i][i]=1;   for(int j=1;j<i;j++)       C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;  } } static void initinv(){  inv[1]=1;  for(int i=2;i<N;i++){   inv[i]=(mod-mod/i)*inv[mod%i]%mod;  } } static void initB(){  B[0]=1;  for(int i=1;i<N;i++){   if(i==N-1) break;   for(int j=0;j<i;j++){    B[i]=(B[i]+C[i+1][j]*B[j]%mod)%mod;   }   B[i]=B[i]*(-inv[i+1]);   B[i]=(B[i]%mod+mod)%mod;  } }    public static void main(String[] args) {  int t,k;  long n;  Scanner cin=new Scanner (System.in);  t=cin.nextInt();  initC();    initinv();  initB();    while(t>0){   t--;   n=cin.nextLong();   n=n%mod; //!!   k=cin.nextInt();   nadd1[0]=1;   for(int i=1;i<=k+1;i++){    nadd1[i]=nadd1[i-1]*(n+1)%mod;   }   long ans=0;   for(int i=1;i<=k+1;i++){    ans=(ans+C[k+1][i]*B[k+1-i]%mod*nadd1[i]%mod)%mod;   }   ans=(ans*inv[k+1]%mod+mod)%mod;   System.out.println(ans);  } }}
当k达到万级时,又是一个工程,我还得继续学习。。。||-_-

0 0
原创粉丝点击