差分序列(poj 2914 Angry Teacher & poj 2515 Birthday Cake)


poj 2515 Birthday Cake

题意:给出m和n,求Sigma(i^m)   0<i<n

解法:最裸的差分序列,根据性质3,只需求得第0条对角线的n+1个值即可。

import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.util.Scanner;
public class Main{
	Scanner scan = new Scanner(System.in);
	BigInteger c[]=new BigInteger[110];
	BigInteger h[][] = new BigInteger[110][110];

	void getc(BigInteger n, int m) {
		c[1] = n;
		for (int i = 2; i <= m+1; i++)
			c[i] = c[i - 1].multiply(n.subtract(BigInteger.valueOf(i - 1)))
					.divide(BigInteger.valueOf(i));
	}
	 PrintWriter out=new PrintWriter(new OutputStreamWriter(System.out));
	void run() {
		int cas=scan.nextInt();
		while(cas-->0){
		BigInteger n =scan.nextBigInteger().add(BigInteger.ONE);
		int m = scan.nextInt();
		for (int i = 0; i <= m; i++)
			h[0][i] = BigInteger.valueOf(i).pow(m);
		for (int i = 1; i <= m; i++)
			for (int j = 0; j <= m - i; j++)
				h[i][j] = h[i - 1][j + 1].subtract(h[i - 1][j]);
		BigInteger ans = BigInteger.ZERO;
		getc(n, m);
		for (int i = 0; i <= m; i++)
			ans=ans.add(h[i][0].multiply(c[i+1]));
		out.println(ans);
		out.flush();
		}
	}

	public static void main(String[] args) {
		new Main().run();
	}
}
poj 2094 Angry Teacher

题意:给出一个多项式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

解法:目测高精暴力应该可以过,但是此题卡的紧,因此考虑用差分序列做对于前n项暴力求出并构造出差分表,对于后n-k项,利用差分表最后一行是一个常数的性质,自底向上递推一次得到第n+1项第n+2项、、、每次只需记录每行最后一个元素的变化即可。

import java.math.BigInteger;
import java.util.Scanner;

public class AngryTeacher {
	BigInteger h[][] = new BigInteger[15][15];
	BigInteger a[] = new BigInteger[15], st, mod;
	int n, m, k;
	Scanner scan = new Scanner(System.in);
	void build() {
		for (int i = 0; i < Math.min(n + 1, k); i++) {
			BigInteger res = a[0];
			for (int j = 1; j <= n; ++j) {
				res = res.multiply(st);
				res = res.add(a[j]);
			}
			res = res.mod(mod);
			st=st.add(BigInteger.ONE);
			h[0][i] = res;
			System.out.println(cal(res.toString()));
		}
		if(k<=n+1) return;
		for (int i = 1; i <= n; i++)
			for (int j = 0; j <= n-i; j++)
				h[i][j] = h[i - 1][j + 1].subtract(h[i - 1][j]);
	}
	BigInteger pre[] = new BigInteger[15];
	void work() {	
		for (int j = 0; j <= n; j++)
			pre[j] = h[j][n-j];		
		for (int i = n + 1; i < k; i++) {
			BigInteger res=h[n][0];
			for(int j=n-1;j>=0;j--){
				res=pre[j].add(res);
				res=res.mod(mod);
				pre[j]=res;
			}
		System.out.println(cal(res.toString()));
		}
	}
	int cal(String s) {
		int len = Math.min(s.length(), m);
		int ans = 0, temp;
		for (int i = 0; i < len; i++) {
			temp = s.charAt(i) - '0';
			ans += temp * temp;
		}
		return ans;
	}
	void init() {
		n = scan.nextInt();
		st = scan.nextBigInteger();
		k = scan.nextInt();
		m = scan.nextInt();
		mod = BigInteger.TEN.pow(m);
		for (int i =0;i<=n; i++)
			a[i] = scan.nextBigInteger();
	}
	void run(){
		init();
		build();
		work();
	}
	public static void main(String[] args) {
		new AngryTeacher().run();
	}
}



  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值