蓝桥杯2014年省赛Java A组

第一题:猜年龄

小明带两个妹妹参加元宵灯会。别人问她们多大了,她们调皮地说:“我们俩的年龄之积是年龄之和的6倍”。小明又补充说:“她们可不是双胞胎,年龄差肯定也不超过8岁啊。”

请你写出:小明的较小的妹妹的年龄。

注意: 只写一个人的年龄数字,请通过浏览器提交答案。不要书写任何多余的内容。

答案:10
Java 代码:

package 省赛JavaA_2014;
//answer:妹妹年龄:10   姐姐年龄:15
public class _01猜年龄 {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		for(int i=1;i<100;i++) {
			for(int j=i+1;j<100;j++) {
				if(6*(i+j)==i*j && j<=(i+8)) {
					System.out.println("妹妹年龄:"+i+"   姐姐年龄:"+j);
				}
			}
		}
	}
}

第二题:李白打酒

话说大诗人李白,一生好饮。幸好他从不开车。

一天,他提着酒壶,从家里出来,酒壶中有酒2斗。他边走边唱:

无事街上走,提壶去打酒。
逢店加一倍,遇花喝一斗。

这一路上,他一共遇到店5次,遇到花10次,已知最后一次遇到的是花,他正好把酒喝光了。 

请你计算李白遇到店和花的次序,可以把遇店记为a,遇花记为b。则:babaabbabbabbbb 就是合理的次序。像这样的答案一共有多少呢?请你计算出所有可能方案的个数(包含题目给出的)。

注意:通过浏览器提交答案。答案是个整数。不要书写任何多余的内容。

答案:14
Java 代码:

package 省赛JavaA_2014;
//answer:14
public class _02李白打酒 {
	static int ans;
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		f(5,9,2);
		System.out.println(ans);
	}
	private static void f(int dian, int hua, int jiu) {
		// TODO Auto-generated method stub
		if(dian==0&&hua==0&&jiu==1) {
			ans++;
			return ;
		}
		if(dian>0) {
			f(dian-1,hua,jiu*2);
		}
		if(hua>0) {
			f(dian,hua-1,jiu-1);
		}
	}
}

第三题:神奇算式

由4个不同的数字,组成的一个乘法算式,它们的乘积仍然由这4个数字组成。

比如: 

210 x 6 = 1260 
8 x 473 = 3784
27 x 81 = 2187 

都符合要求。

如果满足乘法交换律的算式算作同一种情况,那么,包含上边已列出的3种情况,一共有多少种满足要求的算式。

请填写该数字,通过浏览器提交答案,不要填写多余内容(例如:列出所有算式)。
package 省赛JavaA_2014;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
/**
 * 倒数第一行输出最终结果(去除重复的数据)
 * 倒数第二行输出结果(满足交换律的数据被多次累加)
 * 其余输出为满足条件的 两个乘数
 * @author Genius
 */
//answer:12
public class _03神奇算式 {
	static boolean vis[];
	static int a[];
	static int ans=0;
	static Set<Node> set;
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		a = new int[4];
		vis = new boolean[10];
		Arrays.fill(a, 0);
		Arrays.fill(vis,false);
		set = new HashSet<>();
		getFullP(0);//列举每一位的数字
		System.out.println(ans);
		System.out.println(set.size());
	}
	private static void getFullP(int step) {
		// TODO Auto-generated method stub
		if(step==4) {
			judge();
			return ;
		}
		for(int i=0;i<vis.length;i++) {
			if(!vis[i]) {
				a[step]=i;
				vis[i] = true;
				getFullP(step+1);
				vis[i]=false;
			}
		}
	}
	private static void judge() {
		if(a[0]==0) {
			return ;
		}
		//第1位为第一个乘数,第2,3,4为第二个乘数
		int t1 = 0;
		int t2 =0;
		t1 = a[0];
		if(a[1]!=0) {
			t2 = a[1]*100+a[2]*10+a[3];
			int tmp = t1*t2;
			String str = ""+a[0]+a[1]+a[2]+a[3];
			if(judgeIsEqual(str,String.valueOf(tmp))) {
				ans++;
				System.out.println(t1+" "+t2);
				set.add(new Node(t1,t2));
			}	
		}
		t1 = a[0]*10+a[1];
		if(a[2]!=0) {
			t2 =a[2]*10+a[3];
			int tmp = t1*t2;
			String str = ""+a[0]+a[1]+a[2]+a[3];
			if(judgeIsEqual(str,String.valueOf(tmp))) {
				ans++;
				System.out.println(t1+" "+t2);
				set.add(new Node(t1,t2));
			}
		}
		t1 = a[0]*100+a[1]*10+a[2];
		if(a[3]!=0) {
			t2 = a[3];
			int tmp = t1*t2;
			String str = ""+a[0]+a[1]+a[2]+a[3];
			if(judgeIsEqual(str,String.valueOf(tmp))) {
				ans++;
				System.out.println(t1+" "+t2);
				set.add(new Node(t1,t2));
			}
		}
	}
	private static boolean judgeIsEqual(String s1,String result) {
		if(s1.length()!=4||result.length()!=4) {
			return false;
		}
		char c1[] = s1.toCharArray();
		char c2[] = result.toCharArray();
		Arrays.sort(c1);
		Arrays.sort(c2);
		for(int i=0;i<c1.length;i++) {
			if(c1[i]!=c2[i]) {
				return false;
			}
		}
		
		return true;
	}
	static class Node{
		int t1;int t2;

		public Node(int t1, int t2) {
			super();
			this.t1 = t1;
			this.t2 = t2;
		}
		@Override
		public int hashCode() {
			// TODO Auto-generated method stub
			return t1+t2;
		}
		@Override
		public boolean equals(Object obj) {
			// TODO Auto-generated method stub
			Node node = (Node)obj;
			return (t1==node.t1&&t2==node.t2)||(t1==node.t2&&t2==node.t1);
		}
	}
}

第四题:写日志

写日志是程序的常见任务。现在要求在 t1.log, t2.log, t3.log 三个文件间轮流写入日志。也就是说第一次写入t1.log,第二次写入t2.log,... 第四次仍然写入t1.log,如此反复。

下面的代码模拟了这种轮流写入不同日志文件的逻辑。

public class A
{
	private static int n = 1;
	
	public static void write(String msg)
	{
    	String filename = "t" + n + ".log";
    	n = ____________;
    	System.out.println("write to file: " + filename + " " + msg);
   }
}

请填写划线部分缺失的代码。通过浏览器提交答案。

注意:不要填写题面已有的内容,也不要填写任何说明、解释文字。

答案:n%3+1
Java 代码:

package 省赛JavaA_2014;
//answer:n==1?2:n==2?3:1
//answer:n%3+1
public class _04写日志 {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		for(int i=0;i<15;i++) {
			A.write(""+i+i+i+i);
		}
	}
	static public class A
	{
		private static int n = 1;
		public static void write(String msg)
		{
			String filename = "t" + n + ".log";
			//第一种答案
			//n = n==1?2:n==2?3:1;//填空位置
			//第二种答案
			n=n%3+1;
			System.out.println("write to file: " + filename + " " + msg);
		}
	}
}

第五题:锦标赛

    如果要在n个数据中挑选出第一大和第二大的数据(要求输出数据所在位置和值),使用什么方法比较的次数最     少?我们可以从体育锦标赛中受到启发。

 如图【1.png】所示,8个选手的锦标赛,先两两捉对比拼,淘汰一半。优胜者再两两比拼...直到决出第一名。

 第一名输出后,只要对黄色标示的位置重新比赛即可。

下面的代码实现了这个算法(假设数据中没有相同值)。

代码中需要用一个数组来表示图中的树(注意,这是个满二叉树, 不足需要补齐)。它不是存储数据本身,而是存储了数据的下标。   

第一个数据输出后,它所在的位置被标识为-1

class A{
   	//a 表示待处理的数据,长度如果不是2的次幂,则不足位置补为-1
    static void pick(int[] a)
    {
    	int n = 1;
    	while(n<a.length) n *= 2;
	    
	
    	int[] b = new int[2*n-1];
	    for(int i=0; i<n; i++){ 
	    	if(i<a.length) 
	    		b[n-1+i] = i;
	    	else
    			b[n-1+i] = -1;
    	}
	
		//从最后一个向前处理
    	for(int i=b.length-1; i>0; i-=2){
	    	if(b[i]<0){
	    		if(b[i-1]>=0)
	    			b[(i-1)/2] = b[i-1]; 
	    		else
		    		b[(i-1)/2] = -1;
	    	}
	    	else{
		    	if(a[b[i]]>a[b[i-1]])
	    			b[(i-1)/2] = b[i];
	    		else
	    			b[(i-1)/2] = b[i-1];
	    	}
    	}

	//输出树根
	System.out.println(b[0] + ": " + a[b[0]]);
	
	//值等于根元素的位置需要重新pk
	pk(a,b,0,b[0]);
	
	//再次输出树根
	System.out.println(b[0] + ": " + a[b[0]]);
}

// a 表示待处理数据,b 二叉树,k 当前要重新比拼的位置,v 已经决胜出的值	
static void pk(int[] a, int[] b, int k, int v)
{
	
	int k1 = k*2+1;
	int k2 = k1 + 1;
	
	if(k1>=b.length || k2>=b.length){
		b[k] = -1;
		return;
	}
	
	if(b[k1]==v) 
		pk(a,b,k1,v);
	else
		pk(a,b,k2,v);
	
	
	//重新比较
	if(b[k1]<0){
		if(b[k2]>=0)
			b[k] = b[k2]; 
		else
			b[k] = -1;
		return;
	}
	
	if(b[k2]<0){
		if(b[k1]>=0)
			b[k] = b[k1]; 
		else
			b[k] = -1;
		return;
	}
	
	if(__________________________)  //填空
		b[k] = b[k1];
	else
		b[k] = b[k2];
	}
}


请仔细分析流程,填写缺失的代码。

通过浏览器提交答案,只填写缺失的代码,不要填写已有代码或其它说明语句等。

在这里插入图片描述
答案:a[b[k1]]>a[b[k2]]
Java 代码:

package 省赛JavaA_2014;
//answer:a[b[k1]]>a[b[k2]]
public class _05锦标赛 {
	public static void main(String[] args) {
		// TODO Auto-generated method stub
	}
	static class A{
	   	//a 表示待处理的数据,长度如果不是2的次幂,则不足位置补为-1
		static void pick(int[] a)
		{
			int n = 1;
			while(n<a.length) n *= 2;
			int[] b = new int[2*n-1];
			for(int i=0; i<n; i++){ 
				if(i<a.length) 
					b[n-1+i] = i;
				else
					b[n-1+i] = -1;
			}
			//从最后一个向前处理
			for(int i=b.length-1; i>0; i-=2){
				if(b[i]<0){
					if(b[i-1]>=0)
						b[(i-1)/2] = b[i-1]; 
					else
						b[(i-1)/2] = -1;
				}
				else{
					if(a[b[i]]>a[b[i-1]])
						b[(i-1)/2] = b[i];
					else
						b[(i-1)/2] = b[i-1];
				}
			}
			//输出树根
			System.out.println(b[0] + ": " + a[b[0]]);
			//值等于根元素的位置需要重新pk
			pk(a,b,0,b[0]);
			//再次输出树根
			System.out.println(b[0] + ": " + a[b[0]]);
		}
		// a 表示待处理数据,b 二叉树,k 当前要重新比拼的位置,v 已经决胜出的值	
	   	static void pk(int[] a, int[] b, int k, int v)
		{
			int k1 = k*2+1;
			int k2 = k1 + 1;
			
			if(k1>=b.length || k2>=b.length){
				b[k] = -1;
				return;
			}
			if(b[k1]==v) 
				pk(a,b,k1,v);
			else
				pk(a,b,k2,v);
			//重新比较
			if(b[k1]<0){
				if(b[k2]>=0)
					b[k] = b[k2]; 
				else
					b[k] = -1;
				return;
			}
			if(b[k2]<0){
				if(b[k1]>=0)
					b[k] = b[k1]; 
				else
					b[k] = -1;
				return;
			}
			if(a[b[k1]]>a[b[k2]])  //填空
				b[k] = b[k1];
			else
				b[k] = b[k2];
		}
	}
}

第六题:六角填数

如图【1.png】所示六角形中,填入1~12的数字。

使得每条直线上的数字之和都相同。

图中,已经替你填好了3个数字,请你计算星号位置所代表的数字是多少?

请通过浏览器提交答案,不要填写多余的内容。

在这里插入图片描述
答案:10
Java 代码:

package 省赛JavaA_2014;
//answer:10
public class _06六角填数 {
	static int a[]= {2,4,5,6,7,9,10,11,12};
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		getFullP(0);
	}
	/*
	 * 求数组a的全排列
	 */
	private static void getFullP(int step) {
		if(step == a.length) {
			judge();
			return ;
		}
		// TODO Auto-generated method stub
		for(int i=step;i<a.length;i++) {
			int tmp = a[i];
			a[i] = a[step];
			a[step] = tmp;
			getFullP(step+1);
			tmp = a[i];
			a[i] = a[step];
			a[step] = tmp;
		}
	}
	private static void judge() {
		// TODO Auto-generated method stub
		int edge1 = 1+a[0]+a[8]+a[7];
		int edge2 = 1+a[1]+a[3]+a[4];
		int edge3 = 8+a[0]+a[1]+a[2];
		int edge4 = 8+a[8]+a[6]+3;
		int edge5 = a[2]+a[3]+a[5]+3;
		int edge6 = a[7]+a[6]+a[5]+a[4];
		if(edge1==edge2&&edge2==edge3&&edge3==edge4&&edge4==edge5&&edge5==edge6) {
			System.out.println(a[8]);
		}
	}
}

第七题:绳圈

今有 100 根绳子,当然会有 200 个绳头。

如果任意取绳头两两配对,把所有绳头都打结连接起来。最后会形成若干个绳圈(不考虑是否套在一起)。

我们的问题是:请计算最后将形成多少个绳圈的概率最大?

注意:结果是一个整数,请通过浏览器提交该数字。不要填写多余的内容。

答案:3
Java 代码:

package 省赛JavaA_2014;
import java.util.Scanner;
//answer:3
public class _07绳圈 {
	public static void main(String[] args) {
		//用i个绳围成 j 个圈的概率
		//用 i 个绳 所能围成的组合数  c[i] = c[i-1]*(i-1)*2+1;
		//f[i][j] =( f[i-1][j]*c[i-1]*(i-1)*2 + f[i-1][j-1]*c[i-1] ) / c[i]
		//化解得  f[i][j] = (f[i-1][j-1] + f[i-1][j]*[i-1])/(2*i-1)
		double f[][] = new double[101][101];
		f[1][1]=1;
		for (int i = 2; i < f.length; i++) {
			//f[i][1] = f[i - 1][1] * (i - 1) * 2 / (2 * i - 1);
			for (int j = 1; j <=i; j++) {
				f[i][j] = (f[i-1][j-1]+f[i-1][j]*(i-1)*2)/(2*i-1);
			}
		}
		double max = -1;
		int ans = -1;
		for (int i = 1; i < f[0].length; i++) {
			if(f[100][i]>max) {
				max = f[100][i];
				System.out.println(max);
				ans = i;
			}
		}
		System.out.println(ans);
	}
}

第八题:兰顿蚂蚁

兰顿蚂蚁,是于1986年,由克里斯·兰顿提出来的,属于细胞自动机的一种。

平面上的正方形格子被填上黑色或白色。在其中一格正方形内有一只“蚂蚁”。
蚂蚁的头部朝向为:上下左右其中一方。

蚂蚁的移动规则十分简单:
若蚂蚁在黑格,右转90度,将该格改为白格,并向前移一格;
若蚂蚁在白格,左转90度,将该格改为黑格,并向前移一格。

规则虽然简单,蚂蚁的行为却十分复杂。刚刚开始时留下的路线都会有接近对称,像是会重复,但不论起始状态如何,蚂蚁经过漫长的混乱活动后,会开辟出一条规则的“高速公路”。

蚂蚁的路线是很难事先预测的。

你的任务是根据初始状态,用计算机模拟兰顿蚂蚁在第n步行走后所处的位置。

【数据格式】

输入数据的第一行是 m n 两个整数(3 < m, n < 100),表示正方形格子的行数和列数。
接下来是 m 行数据。
每行数据为 n 个被空格分开的数字。0 表示白格,1 表示黑格。

接下来是一行数据:x y s k, 其中x y为整数,表示蚂蚁所在行号和列号(行号从上到下增长,列号从左到右增            长,都是从0开始编号)。s 是一个大写字母,表示蚂蚁头的朝向,我们约定:上下左右分别用:UDLR表示。k   表示蚂蚁走的步数。

输出数据为两个空格分开的整数 p q, 分别表示蚂蚁在k步后,所处格子的行号和列号。


例如, 输入:
5 6
0 0 0 0 0 0
0 0 0 0 0 0
0 0 1 0 0 0
0 0 0 0 0 0
0 0 0 0 0 0
2 3 L 5
程序应该输出:
1 3

再例如, 输入:
3 3
0 0 0
1 1 1
1 1 1
1 1 U 6
程序应该输出:
0 0


资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗  < 1000ms


请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。

所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意:不要使用package语句。不要使用jdk1.7及以上版本的特性。
注意:主类的名字必须是:Main,否则按无效代码处理。

在这里插入图片描述
Java 代码:

package 省赛JavaA_2014;
import java.util.Scanner;
public class _08兰顿蚂蚁 {
static int dir[][]= {{-1,0},{0,1},{1,0},{0,-1}};//上右下左
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc = new Scanner(System.in);
		int m = sc.nextInt();
		int n = sc.nextInt();
		boolean isBlack[][] = new boolean[m][n];
		for (int i = 0; i < isBlack.length; i++) {
			for (int j = 0; j < n; j++) {
				isBlack[i][j] = sc.nextInt() == 0 ? false : true;
			}
		}
		int x = sc.nextInt();
		int y = sc.nextInt();
		String c = sc.next();
		int k = sc.nextInt();
		int current=0;//对应dir数组的第一维下标,如果为0,就是上,1为右,2为下,3为左
		if(c.equals("U")) {
			current = 0;
		}
		else if(c.equals("D")) {
			current = 2;
		}
		else if(c.equals("L")) {
			current = 3;
		}
		else {
			current = 1;
		}
		for(int i=0;i<k;i++) {
			if(isBlack[x][y]) {
				current+=1;//右转
				current=current%4;
				isBlack[x][y]=!isBlack[x][y];//黑格转白格
				x+=dir[current][0];
				y+=dir[current][1];
			}
			else {
				current-=1;//左转
				current = (current+4)%4;
				isBlack[x][y]=!isBlack[x][y];//白格转黑格
				x+=dir[current][0];
				y+=dir[current][1];
			}
		}
		System.out.println(x+" "+y);
	}
}

第九题:斐波那契

斐波那契数列大家都非常熟悉。它的定义是:

f(x) = 1                    .... (x=1,2)
f(x) = f(x-1) + f(x-2)      .... (x>2)

对于给定的整数 n 和 m,我们希望求出:
f(1) + f(2) + ... + f(n)  的值。但这个值可能非常大,所以我们把它对 f(m) 取模。
公式参见【图1.png】

但这个数字依然很大,所以需要再对 p 求模。

【数据格式】
输入为一行用空格分开的整数 n m p (0 < n, m, p < 10^18)
输出为1个整数

例如,如果输入:
2 3 5
程序应该输出:
0

再例如,输入:
15 11 29
程序应该输出:
25

资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗  < 2000ms
请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。

所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意:不要使用package语句。不要使用jdk1.7及以上版本的特性。
注意:主类的名字必须是:Main,否则按无效代码处理。

在这里插入图片描述
Java 代码:

package 省赛JavaA_2014;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.Scanner;
public class _09斐波那契 {
	private static long p;
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc = new Scanner(System.in);
		long n = sc.nextLong();
		long m = sc.nextLong();
		p = sc.nextLong();
		BigInteger fm = fib(m);
		BigInteger sum = fib(n+2).subtract(BigInteger.ONE).mod(fm).mod(BigInteger.valueOf(p));
		System.out.println(sum.toString());
	}
	private static  BigInteger fib(long n) {
		if(n<=2) {
			return BigInteger.ONE;
		}
		BigInteger a[][]= {{BigInteger.ONE,BigInteger.ONE},{BigInteger.ONE,BigInteger.ZERO}};
		BigInteger b[][]= {{BigInteger.ONE,BigInteger.ONE}};
		BigInteger ans =  matrixMultiply(b, matrixPower(a, n-2))[0][0];
		return ans;
	}
	/**
	 * 求矩阵快速幂
	 * @param a 第一个矩阵
	 * @param b 第二个矩阵
	 * @return 返回矩阵相乘结果
	 */
	private static BigInteger[][] matrixMultiply(BigInteger a[][],BigInteger b[][]) {
		BigInteger arr[][] = new BigInteger[a.length][b[0].length];
		for (int i = 0; i < arr.length; i++) {
			for (int j = 0; j < arr[i].length; j++) {
				arr[i][j]=BigInteger.ZERO;
			}
		}
		for(int i =0;i<a.length;i++) {
			for(int j=0;j<b[0].length;j++) {
				for(int k=0;k<a[0].length;k++) {
					arr[i][j]=(arr[i][j].add(a[i][k].multiply(b[k][j])));
				}
			}
		}
		return arr;
	}
	/**
	 * 使用快速幂算法,求矩阵a的n次幂
	 * @param a
	 * @param n
	 * @return
	 */
	private static BigInteger[][] matrixPower(BigInteger a[][],long n){
		BigInteger ans[][] = new BigInteger[a.length][a[0].length];
		for(int i=0;i<ans.length;i++) {
			for(int j=0;j<ans[0].length;j++) {
				ans[i][j] = i==j?BigInteger.ONE:BigInteger.ZERO;
			}
		}
		while(n!=0) {
			if((n&1)==1) {
				ans = matrixMultiply(ans,a);
			}
			a = matrixMultiply(a, a);
			n=n>>1;
		}
		return ans;
	}
}

第十题:波动数列

观察这个数列:
1 3 0 2 -1 1 -2 ...

这个数列中后一项总是比前一项增加2或者减少3。

栋栋对这种数列很好奇,他想知道长度为 n 和为 s 而且后一项总是比前一项增加a或者减少b的整数数列可能有多少种呢?

【数据格式】
    输入的第一行包含四个整数 n s a b,含义如前面说述。
    输出一行,包含一个整数,表示满足条件的方案数。由于这个数很大,请输出方案数除以100000007的余数。

例如,输入:
4 10 2 3
程序应该输出:
2

【样例说明】
这两个数列分别是2 4 1 3和7 4 1 -2。

【数据规模与约定】
对于10%的数据,1<=n<=5,0<=s<=5,1<=a,b<=5;
对于30%的数据,1<=n<=30,0<=s<=30,1<=a,b<=30;
对于50%的数据,1<=n<=50,0<=s<=50,1<=a,b<=50;
对于70%的数据,1<=n<=100,0<=s<=500,1<=a, b<=50;
对于100%的数据,1<=n<=1000,-1,000,000,000<=s<=1,000,000,000,1<=a, b<=1,000,000。

资源约定:
峰值内存消耗(含虚拟机) < 256M
CPU消耗  < 2000ms


请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。

所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意:不要使用package语句。不要使用jdk1.7及以上版本的特性。
注意:主类的名字必须是:Main,否则按无效代码处理。

Java 代码:

package 省赛JavaA_2014;
import java.util.Scanner;
public class _10波动数列 {
	  private static int n;
	  private static long s;
	  private static long a;
	  private static long b;
	  public static void main(String[] args) {
	    Scanner sc = new Scanner(System.in);
	    n = sc.nextInt();
	    s = sc.nextLong();
	    a = sc.nextLong();
	    b = sc.nextLong();
	    int t = n * (n - 1) / 2;
	    int[] dp = new int[t + 1];
	    dp[0] = 1;
	    for (int i = 1; i <= n - 1; i++) {
	      for (int j = i * (i + 1) / 2; j >= i; j--) {
	        // dp[j] += dp[j - i];
	        // if (dp[j] > 100000007) dp[j] %= 100000007;
	        dp[j] = (dp[j] + dp[j - i]) % 100000007;
	      }
	    }
	    long ans = 0;
	    for (int i = 0; i <= t; i++) {
	      if ((s - i * a + (t - i) * b) % n == 0)
	        ans = (ans + dp[i]) % 100000007;
	      // if (ans > 100000007) ans %= 100000007;
	    }
	    System.out.println(ans);
	  }
}

等以后有时间再慢慢写注释吧

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值