【Mail.Ru Cup 2018 Round 3 B. Divide Candies】分析+暴力


B. Divide Candies

题意

给你一个n*n的方格,点(i,j)的权值为 i 2 + j 2 i^2+j^2 i2+j2
问这个方格内有多少个数是m的倍数
1 &lt; = n &lt; = 1 0 9 , 1 &lt; = m &lt; = 1000 1&lt;=n&lt;=10^9,1&lt;=m&lt;=1000 1<=n<=109,1<=m<=1000

做法

由 于 m 的 数 据 范 围 很 小 , 我 们 可 以 直 接 算 出 m ∗ m 之 内 的 是 m 的 倍 数 的 个 数 由于m的数据范围很小,我们可以直接算出m*m之内的是m的倍数的个数 mmmm
如 果 把 m ∗ m 这 个 矩 形 内 的 所 有 点 的 横 坐 标 + m , m 的 倍 数 的 个 数 还 是 不 变 的 如果把m*m这个矩形内的所有点的横坐标+m,m的倍数的个数还是不变的 mm+mm
纵 坐 标 同 理 , 于 是 我 们 算 出 n ∗ n 中 包 含 多 少 个 m ∗ m , 之 后 同 理 再 算 剩 下 的 小 块 纵坐标同理,于是我们算出n*n中包含多少个m*m,之后同理再算剩下的小块 nnmm,
复 杂 度 O ( n l o g n ) 复杂度O(nlogn) O(nlogn)
在这里插入图片描述
如上图蓝色阴影用蓝色块翻倍算,红色阴影用红色块翻倍算,紫色块自己算
代码

#include<stdio.h>
typedef long long ll;
int main()
{
    ll n,m;
    scanf("%lld%lld",&n,&m);
    ll cnt=0;
    for(ll i=1;i<=m;i++)
    {
        for(ll j=1;j<=m;j++)
        {
            ll tmp=i*i+j*j;
            if(tmp%m==0) cnt++;
        }
    }
    ll ans=((n/m)*(n/m))*cnt;
    cnt=0;
    for(ll i=(n-n%m)+1;i<=n;i++)
    {
        for(ll j=1;j<=m;j++)
        {
            ll tmp=i*i+j*j;
            if(tmp%m==0) cnt++;
        }
    }
    ans+=2LL*cnt*(n/m);
    cnt=0;
    for(ll i=(n-n%m)+1;i<=n;i++)
    {
        for(ll j=(n-n%m)+1;j<=n;j++)
        {
            ll tmp=i*i+j*j;
            if(tmp%m==0) cnt++;
        }
    }
    ans+=cnt;
    printf("%lld\n",ans);
    return 0;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值