The 2020 ICPC Asia Shenyang Regional Programming Contest I题 Rise of Shadows(数论)

题目链接The 2020 ICPC Asia Shenyang Regional Programming Contest

The 2020 ICPC Asia Shenyang Regional Programming Contest I题 Rise of Shadows(数论)_第1张图片
题目大意:
一天内有H小时,每小时M分钟,时针分针以恒定速率旋转。
现在若时针分针的夹角<=α,则该时刻的分钟是贡献分钟。
现在要求解一天里面的所有贡献分钟。

分析:
计算两个速率V1 V2,枚举小时【0,N-1】
计算该小时内的有效分钟,显然是圆上弧长有一定关系,不妨写出如下暴力

for(int i=0; i<n; i++)
{
    for(int j=0; j<m; j++)
    {
        if(abs(m*i+j-n*j)<=k)
            ans++;
    }
}

考虑到该方程要等于【0,K】时才有效,考虑到该方程有解的前提是Ki 整除gcd(n-1,m),因此可以快速计算出有效的K有 K/gcd(n-1,m)个,考虑到绝对值的关系,每组还要乘2。 再考虑下K=0,记为1 ,对于K=0 不难发现只有gcd(n-1,m)组解,同理对于其他有效K。那么最终答案为 (K/g*2+1)*g
PS:此做法不是很严谨
缺少证明 m * x +(1-n) * y=Q 的解的个数 x<=m且y<=n-1且x y大于等于0个数为gcd(n-1,m)个。
因此附上类欧几里得算法写法即求解 abs(m * x+(1-n) * y)<=K
将绝对值拆开,做两次类欧几里得算法。结尾附上代码QAQ

signed main()
{
    ll n,m,k;
    read(n);
    read(m);
    read(k);
    ll ans=0;
    if(k*2==n*m)
    {
        printf("%lld",n*m);
        return 0;
    }
    ll g=gcd(n-1,m);
    printf("%lld\n",(k/g*2+1)*g);
}
#include
using namespace std;
#define ll long long
#define int long long

int n, a, b, c;
//f(a,b,c,n)=sum(i,0,n)[(a*i+b)/c]
//g(a,b,c,n)=sum(i,0,n)i*[(a*i+b)/c]
//h(a,b,c,n)=sum(i,0,n)[(a*i+b)/c]的平方
struct node {
    int f, g, h;
};
node solve(ll a, ll b, ll c, ll n) {
    node ans;
    if (!a) {
        ans.f = (n + 1) * (b / c) ;
        ans.g = (n + 1) * n / 2 * (b / c);
        ans.h = (n + 1) * (b / c) * (b / c);
        return ans;
    }
    if ((a >= c) || (b >= c)) {
        node tmp = solve(a % c, b % c, c, n);
        ans.f = (tmp.f + n * (n + 1) / 2 * (a / c) + (n + 1) * (b / c));
        ans.g = (tmp.g + n * (n + 1) * (n * 2 + 1) / 6 * (a / c) + n * (n + 1) / 2 * (b / c));
        ans.h = (tmp.h + n * (n + 1) * (n * 2 + 1) / 6 * (a / c) * (a / c) + (n + 1) * (b / c) * (b / c) + tmp.f * (b / c) * 2 + tmp.g * (a / c) * 2 + (a / c) * (b / c) * n * (n + 1));
        return ans;
    }
    ll m = (a * n + b) / c;
    node tmp = solve(c, c - b - 1, a, m - 1);
    ans.f = (n * m  - tmp.f);
    ans.g = (m * n * (n + 1) - tmp.f - tmp.h) / 2;
    ans.h = (n * m * (m + 1) - tmp.g * 2 - tmp.f * 2 - ans.f);
    return ans;
}
int qpow(int x, int y) {
    int ans = 1;
    while (y) {
        if (y & 1)ans = ans * x;
        y >>= 1; x = x * x;
    }return ans;
}
int gcd(int a, int b) { return b ? gcd(b, a % b) : a; }
int exgcd(int a, int b, int& x, int& y) {
    int d = a;                            //x是a在膜b下的逆元
    if (b != 0) {                           //-b+1~b-1最后判负要加b
        d = exgcd(b, a % b, y, x);
        y -= (a / b) * x;
    }
    else {
        x = 1; y = 0;
    }
    return d;	        //返回gcd(a,b)
}
int fuc(int a, int b, int c, int n)
{
    a %= c, b %= c;
    int z = gcd(a, c);
    if (b % z) return 0;
    int x, y;
    exgcd(a, c, x, y);
    x *= (-b / z);
    x %= (c / z);
    if (x < 0) x += (c / z);
    int ret = (n - x) / (c / z) + 1;
    return max(ret, 0ll);
}

signed main() 
{
	ll h, m, a;
	cin >> h >> m >> a;
	int k = a / (h - 1) + 1;
	node ans1 = solve(h * m, a + k * (h - 1), h - 1, h - 2);
	node ans2 = solve(h * m, -a + k * (h - 1), h - 1, h - 2);
	ll ans = ans1.f - ans2.f + fuc(h * m, -a + k * (h - 1), h - 1, h - 2);
	cout << min(ans, h * m) << endl;

}

你可能感兴趣的:(The 2020 ICPC Asia Shenyang Regional Programming Contest I题 Rise of Shadows(数论))