1. 程式人生 > >【Mail.Ru Cup 2018 Round 3 B. Divide Candies】分析+暴力

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


B. Divide Candies

題意

給你一個n*n的方格,點(i,j)的權值為 i 2 + j 2 i^2+j^2


問這個方格內有多少個數是m的倍數
1 < = n < = 1 0
9 , 1 < = m < = 1000
1<=n<=10^9,1<=m<=1000

做法

m m m m 由於m的資料範圍很小,我們可以直接算出m*m之內的是m的倍數的個數
m m + m m 如果把m*m這個矩形內的所有點的橫座標+m,m的倍數的個數還是不變的
n n m m , 縱座標同理,於是我們算出n*n中包含多少個m*m,之後同理再算剩下的小塊
O ( n l o g n ) 複雜度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;
}