結果

問題 No.3031 (物理学)長距離相互作用
ユーザー 37zigen37zigen
提出日時 2016-09-08 17:25:25
言語 Java21
(openjdk 21)
結果
AC  
実行時間 1,954 ms / 10,000 ms
コード長 4,689 bytes
コンパイル時間 3,176 ms
コンパイル使用メモリ 75,652 KB
実行使用メモリ 64,680 KB
最終ジャッジ日時 2023-08-26 19:12:00
合計ジャッジ時間 27,065 ms
ジャッジサーバーID
(参考情報)
judge12 / judge14
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 1,903 ms
62,068 KB
testcase_01 AC 1,921 ms
64,204 KB
testcase_02 AC 1,906 ms
62,456 KB
testcase_03 AC 1,951 ms
62,124 KB
testcase_04 AC 1,888 ms
62,184 KB
testcase_05 AC 1,844 ms
62,032 KB
testcase_06 AC 1,888 ms
64,680 KB
testcase_07 AC 1,852 ms
62,056 KB
testcase_08 AC 1,896 ms
61,916 KB
testcase_09 AC 1,821 ms
61,696 KB
testcase_10 AC 1,954 ms
64,088 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

package 作問;

import java.util.Scanner;

public class Q001_answer {
	public static void main(String[] args) {
		new Q001_answer().solver();
	}

	void solver() {

		double constant_of_NaCl = calculator(0) * 2;
		double constant_of_CsCl = calculator(1);

		Scanner sc = new Scanner(System.in);
		double A = 0, B = 0, C = 0, D = 0, E = 0;
		A += sc.nextDouble();
		B += sc.nextDouble();
		B += sc.nextDouble();
		C += sc.nextDouble();
		B += sc.nextDouble();
		C += sc.nextDouble();
		C += sc.nextDouble();
		D += sc.nextDouble();
		for (int i = 0; i < 8; i++)
			E += sc.nextDouble();

		assert 4 * (A + D) + E == 0;
		assert (A + B + C + D + E) == 0;
		
		final double m100 = -1.0 / 6.0 * constant_of_NaCl + 1.0 / 3.0 * constant_of_CsCl;
		final double m110 = 1.0 / 6.0 * constant_of_NaCl;

		System.out.println((3 * A + B) * m100 + (3 * A + C) * m110);

	}

	double[][] make_sample_of_NaCl() {
		double[][] p = new double[4][27];

		for (int i = 0; i < 3; i++) {
			for (int j = 0; j < 3; j++) {
				for (int k = 0; k < 3; k++) {
					p[0][(9 * i + 3 * j + k)] = i;
					p[1][(9 * i + 3 * j + k)] = j;
					p[2][(9 * i + 3 * j + k)] = k;
					p[3][(9 * i + 3 * j + k)] = (i + j + k) % 2 == 0 ? 1 : -1;
				}
			}
		}
		return p;
	}

	// NaCl:0
	// CsCl:1
	double calculator(int isNaClorCsCl) {

		double[][] p = make_sample_of_NaCl();

		double[][] axis = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 } };
		if (isNaClorCsCl == 1)
			axis = new double[][] { { 0.5, 0.5, -0.5 }, { -0.5, 0.5, 0.5 }, { 0.5, -0.5, 0.5 } };
		double sum = 0;

		// i is the level.
		// p1 and p2 show the point of the cell.
		// for (int i = 0; i <= 50; i++) {
		// for (int p1 = 0; p1 <= i; p1++) {
		// for (int p2 = 0; p2 <= i; p2++) {
		// sum += calc(p1, p2, i, p, axis);
		// sum += calc(p2, i, p1, p, axis);
		// sum += calc(i, p1, p2, p, axis);
		// }
		// sum -= calc(i, i, p1, p, axis);
		// sum -= calc(i, p1, i, p, axis);
		// sum -= calc(p1, i, i, p, axis);
		// }
		// sum += calc(i, i, i, p, axis);
		// }
		for (int i = isNaClorCsCl == 0 ? 0 : -50; i <= 50; i++) {
			for (int j = isNaClorCsCl == 0 ? 0 : -50; j <= 50; j++) {
				for (int k = 0; k <= 50; k++) {
					sum += calc(i, j, k, p, axis);
				}
			}
		}
		return sum * (isNaClorCsCl == 0 ? 8 : 2);
	}

	double calc(int nx, int ny, int nz, double[][] p, double[][] axis) {
		double sum = 0;
		int n = p[0].length;
		for (int i = 0; i < n; i++) {
			double x = 2 * nx + p[0][i];
			double y = 2 * ny + p[1][i];
			double z = 2 * nz + p[2][i];
			if (x == 0 && y == 0 && z == 0)
				continue;
			double coe = 1;
			if ((p[0][i] == 2 || p[0][i] == 0) && (p[1][i] == 2 || p[1][i] == 0) && (p[2][i] == 2 || p[2][i] == 0))
				coe *= solid_angle(p[0][i] == 2 ? vector_minus(axis[0]) : axis[0],
						p[1][i] == 2 ? vector_minus(axis[1]) : axis[1], p[2][i] == 2 ? vector_minus(axis[2]) : axis[2])
						/ (4 * Math.PI);
			else if (((p[0][i] == 2 || p[0][i] == 0) && (p[1][i] == 2 || p[1][i] == 0))
					|| ((p[1][i] == 2 || p[1][i] == 0) && (p[2][i] == 2 || p[2][i] == 0))
					|| ((p[2][i] == 2 || p[2][i] == 0) && (p[0][i] == 2 || p[0][i] == 0))) {
				double[][] v = new double[2][3];
				int c = 0;
				for (int j = 0; j < 3; j++) {
					if (p[j][i] == 2 || p[j][i] == 0) {
						if (p[j][i] == 2)
							v[c++] = vector_minus(axis[j]);
						else
							v[c++] = axis[j];
					}
				}
				coe *= dihedral_angle(v[0], v[1]) / (2 * Math.PI);
			} else if ((p[0][i] == 2 || p[0][i] == 0) || (p[1][i] == 2 || p[1][i] == 0)
					|| (p[2][i] == 2 || p[2][i] == 0))
				coe *= 0.5;
			sum += p[3][i] / dist(0, 0, 0, x, y, z, axis) * coe;
		}
		return sum;
	}

	double dist(double x1, double y1, double z1, double x2, double y2, double z2, double[][] axis) {
		return Math.sqrt((x1 - x2) * (x1 - x2) * dot_product(axis[0], axis[0])
				+ (y1 - y2) * (y1 - y2) * dot_product(axis[1], axis[1])
				+ (z1 - z2) * (z1 - z2) * dot_product(axis[2], axis[2])
				+ dot_product(axis[0], axis[1]) * 2 * (x1 - x2) * (y1 - y2)
				+ dot_product(axis[1], axis[2]) * 2 * (y1 - y2) * (z1 - z2)
				+ dot_product(axis[2], axis[0]) * 2 * (z1 - z2) * (x1 - x2));
	}

	double dot_product(double[] p, double[] q) {
		double ret = 0;
		for (int i = 0; i < 3; i++) {
			ret += p[i] * q[i];
		}
		return ret;
	}

	double dihedral_angle(double[] p, double[] q) {
		return Math.acos(dot_product(p, q) / (vector_length(p) * vector_length(q)));
	}

	double vector_length(double[] p) {
		return Math.sqrt(dot_product(p, p));
	}

	double solid_angle(double[] v1, double[] v2, double[] v3) {
		return dihedral_angle(v1, v2) + dihedral_angle(v2, v3) + dihedral_angle(v3, v1) - Math.PI;
	}

	double[] vector_minus(double[] v) {
		return new double[] { -v[0], -v[1], -v[2] };
	}
}
0