题目地址:https://codeforces.com/gym/101964/problem/B
题目:
给出表盘的时针、分针、秒针的长度A, B, C和表盘刻度数N,求时针、分针、秒针任意指向一个刻度,针点构成的包含圆心的三角形数目(包括圆心在三角形边上的情况)
解题思路:
为了简化问题,我们先考虑A=B=C的情况,其他情况就是在此基础上进行多重排列了。
(1)N为偶数
整个圆上的点都是对称的,固定一个点A,枚举另一个点B,可以确定C的可取点在A和B关于原点的对称点A'B'之间,包括边界上的点。为了避免重复,只枚举上半部分的A, 最终*2就是答案。
例如:N=10
枚举方法:令m=N/2-1
A在A,B在B/C/D/E,可以确定的三角形数为:2+3+4+5
A在B,B在C/D/E,可以确定的三角形数为:2+3+4
A在C,B在D/E,可以确定的三角形数为:2+3
A在D,B在E,可以确定的三角形数为:2
通过等差数列的求和公式和1^2+2^2+...+n^2=n(n+1)(2n+1)/6,可以推出公式:
(2)N为基数
和N为偶数的枚举思路基本一致,但是当N为基数时,除了在x轴上的一个点之外,其他的点是上下对称的,故x轴上点需要单独枚举,其他的只需要枚举上半部分的点。
例如N=7:
枚举方法:令m=N/2
A在A点,B在B/C/D点,可以确定的三角形数为:1+2+3
A在B点,B在C/D点,可以确定的三角形数为:1+2
A在C点,B在D点,可以确定的三角形数为:1
通过等差数列的求和公式和1^2+2^2+...+n^2=n(n+1)(2n+1)/6,可以推出公式:
当三条边是ABC类型的,ans=ans*6;当三条边是AAB类型的,ans=ans*3
注意:答案要对2^64取模,相当于自然溢出,可以用unsigned long long ,但是在计算ans的分子是自然溢出之后的值会小于分母,用逆元的话又有些麻烦,既然ans为正数,可以先用分子一点点把分母消掉再乘起来。(或者直接用java写)
ac代码:
c++
#include <iostream>
#include <math.h>
using namespace std;
typedef unsigned long long ll;
ll A, B, C, N;
int judge()
{
if(A == B && B == C) return 3;
else if(A != B && B != C) return 1;
else return 2;
}
ll gcd(ll a, ll b)
{
return b == 0 ? a : gcd(b, a%b);
}
int main()
{
cin >> A >> B >> C >> N;
if(N == 2) printf("0");
else
{
int e = judge();
ll m = N / 2, ans;
if(N%2 == 0)
{
m--;
ll a = m, b = m+1, c = m+5;
if(a%3 == 0) a /= 3;
else if(b%3 == 0) b /= 3;
else if(c%3 == 0) c /= 3;
ans = a * b * c;
}
else
{
ll a = m, b = m+1, c = 2*m+1, mul = 1;
ll ga = gcd(a, 6), gb = gcd(b, 6), gc = gcd(c, 6);
if(ga != 1 && mul != 6) a /= ga, mul *= ga;
if(gb != 1 && mul != 6) b /= gb, mul *= gb;
if(gc != 1 && mul != 6) c /= gc, mul *= gc;
ans = a * b * c;
}
if(e == 1)
ans = ans * 6;
else if(e == 2)
ans = ans * 3;
cout << ans;
}
return 0;
}
JAVA:
import java.math.BigInteger;
import java.util.*;
public class Main
{
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
BigInteger A = input.nextBigInteger();
BigInteger B = input.nextBigInteger();
BigInteger C = input.nextBigInteger();
BigInteger N = input.nextBigInteger();
BigInteger x1 = new BigInteger("1");
BigInteger x2 = new BigInteger("2");
BigInteger x5 = new BigInteger("5");
BigInteger x3 = new BigInteger("3");
BigInteger x6 = new BigInteger("6");
BigInteger x0 = new BigInteger("0");
BigInteger MOD = x2.pow(64);
BigInteger ans;
int e = 0;
if(A.equals( B) && B.equals(C)) e = 3;
else if(!A.equals(B) && !B.equals(C) && !A.equals(C)) e = 1;
else e = 2;
BigInteger m = N.divide(x2);
if((N.mod(x2)).equals(x0))
{
m = m.subtract(x1);
BigInteger a = m;
BigInteger b = m.add(x1);
BigInteger c = m.add(x5);
ans = a.multiply(b).multiply(c).divide(x3);
}
else
{
BigInteger a = m;
BigInteger b = m.add(x1);
BigInteger c = m.multiply(x2).add(x1);
ans = a.multiply(b).multiply(c).divide(x6);
}
if(e == 2) ans = ans.multiply(x3);
else if(e == 1) ans = ans.multiply(x6);
System.out.print(ans.mod(MOD));
}
}