2018-方格计数
/*
标题:方格计数
在二维平面上有无数个1x1的小方格。
我们以某个小方格的一个顶点为圆心画一个半径为1000的圆。
你能计算出这个圆里有多少个完整的小方格吗?
注意:需要提交的是一个整数,不要填写任何多余内容。
*/
//思路:将中心看作象限的中点,遍历第一象限的右上角,只要右上角处于圈内即所代表的方格处于圈内(勾股定理)
public class 方格计数 {
public static void main(String[] args) {
long n=0;
for (int i = 1; i <= 1000; i++) {
for (int j = 1; j <= 1000; j++) {
if(i*i+j*j<=1000*1000){
n++;
}
}
}
System.out.println(n*4);
}
}
这道题还是挺简单的,还有数边的的较优解,但感觉没看的必要
2018-测试次数
/*
x星球有很多高耸入云的高塔,刚好可以用来做耐摔测试。塔的每一层高度都是一样的,与地球上稍有不同的是,他们的第一层不是地面,而是相当于我们的2楼。
如果手机从第7层扔下去没摔坏,但第8层摔坏了,则手机耐摔指数=7。
特别地,如果手机从第1层扔下去就坏了,则耐摔指数=0。
如果到了塔的最高层第n层扔没摔坏,则耐摔指数=n
为了减少测试次数,从每个厂家抽样3部手机参加测试。
某次测试的塔高为1000层,如果我们总是采用最佳策略,在最坏的运气下最多需要测试多少次才能确定手机的耐摔指数呢?
*/
思路:
首先,最佳策略即即为是在每次运气最差时取得的最小值
手机数量(F)和层数(N)是固定的,测试次数F[i]则可分情况进行判断
F=1;N=1000:当只有一部手机时只能从下挨个进行测试 F[N]=N
F=2;N=1000:两部手机时,则可进行选择测试(先测试i层再分情况判断),
1)、如果测试后手机状态为好,那么F=2,N=1000-i(继续判断i层之上)
2)、但如果手机为坏时,手机只剩一部,这样又需要进行F=1时的情况,那这样F[N]=1+F[i]
这样的最佳策略还是有些模糊,那我们就将i的值从1开始遍历
假使F=2&&N=4时:
当状态为好时,F[N]=1+t(F,N-i)
当状态为坏时,F[N]=1+t(F-1,N-1)
也就是说当手机数量F=1时的测试次数已知,而当F++时我们总能通过已知的F[i]计算出F[i+1]的值,直到i+1=N;
这样可以设立三个数组,挨个定义其中的值只需要最后输出F3[N]的值
public class 测试次数 {//手机数与楼层数为固定值,最优策略为每种情况下运气差的值中的最小值(所有最大值中的最小值)
static final int N = 1000;//设置常量层数
static int[] f1 = new int[N + 1];
static int[] f2 = new int[N + 1];
static int[] f3 = new int[N + 1];
public static void main(String[] args) {
//当只有一部手机的情况
for (int i = 1; i <= N; i++) {
f1[i] = i;
}
//两部手机的情况
for (int i = 1; i <= N; i++) {
int ans = Integer.MAX_VALUE;
for (int j = 1; j <= i; j++) { //不能直接通过N进行计算,内循环一步步算上去
int _max = 1 + Math.max(f2[i - j], f1[j - 1]);//选择每层进行测试时运气差的那一次
ans = Math.min(ans, _max);//所有差运气中的最佳策略
}
f2[i] = ans;
}
//三部手机的情况
for (int i = 1; i <= N; i++) {
int ans = Integer.MAX_VALUE;
for (int j = 1; j <= i; j++) {
int _max = 1 + Math.max(f3[i - j], f2[j - 1]);
ans = Math.min(ans, _max);
}
f3[i] = ans;
}
System.out.println(f3[N]);
}
}
还有一个二维数组的写法,思路也是这样的,就不重复啰嗦了
2018-螺旋曲线
问题:
如图p1.png所示的螺旋折线经过平面上所有整点恰好一次。
对于整点(X, Y),我们定义它到原点的距离dis(X, Y)是从原点到(X, Y)的螺旋折线段的长度。
例如dis(0, 1)=3, dis(-2, -1)=9
给出整点坐标(X, Y),你能计算出dis(X, Y)吗?
【输入格式】
X和Y
对于40%的数据,-1000 <= X, Y <= 1000
对于70%的数据,-100000 <= X, Y <= 100000
对于100%的数据, -1000000000 <= X, Y <= 1000000000
【输出格式】
输出dis(X, Y)
【样例输入】
0 1
【样例输出】
3
思路:
在二四象限作一条斜线分割此折线
这样每一个右下角的折点的距离即为右上N个三角形的两边和与左下N个三角形的两边和(其中N为折点的X轴坐标),这样将两边的三角形合看作一个等差数列,进行求和,再判断每个点距离与他最近的折点的距离,进行加或减
public class 螺旋折线 {
public static void main(String[] args) {
Scanner input=new Scanner(System.in);
long x=input.nextLong();
long y=input.nextLong();
long n=0;//定义圈数
long d=0;//长度
if(y>0&&Math.abs(x)<=y){
n=y;
d=y-x+2*y;
} else if(x>0&&Math.abs(y)<=x){
n=x;
d=x+y;
}else if(y<=0&&x>=y-1&&x<=-y){
n=-y;
d=-(-y-x);//将长度转为负数,后边负负得正
}else if(x<0&&y>=x+1&&y<=-x){
n=-x-1;
d=-(y-x-1-2*x-1);
}
System.out.println(sum(6,n,8)-d);
//将两个等差数列合为一个,减去d的值(左下的值为负数即加上)
}
public static long sum(long a0,long n,long d){//等差数列求和方法
return (2*a0+(n-1)*d)*n/2;
}
}
2018-复数幂
问题:
设i为虚数单位。对于任意正整数n,(2+3i)^n 的实部和虚部都是整数。
求 (2+3i)^123456 等于多少? 即(2+3i)的123456次幂,这个数字很大,要求精确表示。
答案写成 “实部±虚部i” 的形式,实部和虚部都是整数(不能用科学计数法表示),中间任何地方都不加空格,实部为正时前面不加正号。
(2+3i)^2 写成: -5+12i,
(2+3i)^5 的写成: 122-597i
注意:需要提交的是一个很庞大的复数,不要填写任何多余内容。
思路:
用循环实现幂,a代表实部,b代表虚部,因为最后的值很大,所以开始就定义为Big型。循环一次后实部=2a-(3b),虚部=3a+2b。
public class 负数幂 {
public static void main(String[] args) throws FileNotFoundException {
BigInteger two = BigInteger.valueOf(2);//2和3不能直接用所以定义为BigInteger型
BigInteger three = BigInteger.valueOf(3);
BigInteger a = BigInteger.valueOf(2);
BigInteger b = BigInteger.valueOf(3);
BigInteger aa = null;
BigInteger bb = null;
for (int i = 0; i < 123455; i++) {
aa = a.multiply(two).subtract(b.multiply(three));//a*2-(b*3)
bb = a.multiply(three).add(b.multiply(two));//a*3+b*2
a = aa;//将aa的值赋予a中进行下次循环
b = bb;
}
//System.setOut(new PrintStream(new File("E:\\out.txt")));//输出到文本以查看
System.out.println(aa + (bb.compareTo(BigInteger.ZERO) < 0 ? "-" : "+") + bb + "i");
//bb.compareTo(BigInteger.ZERO) < 0 ? "-" : "+" 判断bb是否小于0,小于输出一个负号,大于输出加号
}
}
2018-递归三元组
题目:
给定三个整数数组
A = [A1, A2, … AN],
B = [B1, B2, … BN],
C = [C1, C2, … CN],
请你统计有多少个三元组(i, j, k) 满足:
- 1 <= i, j, k <= N
- Ai < Bj < Ck
【输入格式】
第一行包含一个整数N。
第二行包含N个整数A1, A2, … AN。
第三行包含N个整数B1, B2, … BN。
第四行包含N个整数C1, C2, … CN。
对于30%的数据,1 <= N <= 100
对于60%的数据,1 <= N <= 1000
对于100%的数据,1 <= N <= 100000 0 <= Ai, Bi, Ci <= 100000
【输出格式】
一个整数表示答案
【输入样例】
3
1 1 1
2 2 2
3 3 3
【输出样例】
27
思路:
首先将三组数自小到大进行排列,
以b组做判断,a组中比b组小的的下标为p个,c组中比b组大的的下标为n-q个
也就是说,p*(n-q)的值就是当j固定时(i,j,k)的个数
遍历b组,将每一组符合条件的p*(n-q)加起来的总和就是所有(i,j,k)的个数
public class 递归三元组 {
public static void main(String[] args) {
Scanner input=new Scanner(System.in);
int N=input.nextInt();
int[] a=new int[N];
int[] b=new int[N];
int[] c=new int[N];
for (int i = 0; i < N; i++) {
a[i]=input.nextInt();
}
for (int i = 0; i < N; i++) {
b[i]=input.nextInt();
}
for (int i = 0; i < N; i++) {
c[i]=input.nextInt();
}
Arrays.sort(a);
Arrays.sort(b);
Arrays.sort(c);
int p=0,q=0;
long ans=0;
for (int i = 0; i < N; i++) {
while (p<N&&a[p]<b[i])p++;
while (q<N&&c[q]<=b[i])q++;
ans+=1L*p*(N-q);//因为ans是一个长整型,所以在乘式前加上1L将其转换格式
}
System.out.println(ans);
}
}
这篇帖子就到这了,以后也不更了,毕竟是为了比赛刷的题,得有针对性啊,一点数据结构的基础也没有,所以后边太难的就不研究了