1. 程式人生 > >[codeforces Mail.Ru Cup 2018 Round 3][B Divide Candies ][思維+數學]

[codeforces Mail.Ru Cup 2018 Round 3][B Divide Candies ][思維+數學]

https://codeforces.com/contest/1056/problem/B

題意:輸入n,m    求((a*a)+(b*b))%m==0的(a,b)種數(1<=a,b<=n) (n<=1e9,m<=1000)

題解:由於a,b的數量級很大,而m的數量級很小,又因為求((a*a)+(b*b))%m==0,即求((a%m*a%m)+(b%m*b%m))%m==0滿足要求的a,b對數,也就是求a%m,b%m的平方分別取模後相加為0或者m的a,b對數,由於此時問題只和a%m平方取模的結果以及b%m平方取模的結果有關而且(a%m)和(b%m)為0~m-1的數,所以可以直接預處理出0~m-1數平方取模後的結果,然後直接通過計算1~n之間的數對m取模後得到相應(a%m)和(b%m)的個數,把相匹配的(a%m)和(b%m)的個數相乘即可.而求取模結果為x的個數就很容易了(P.S. 比賽的時候真的zz,求個數過程把大於等於寫成等於..導致wa到懷疑人生...)

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<queue>
 6 #include<vector>
 7 #include<map>
 8 using namespace std;
 9 typedef  long long  ll;
10 ll kk[1005];
11 int main(){
12  //freopen("in.txt","r",stdin);
13 ll n,m; 14 cin>>n>>m; 15 vector<int>vc[1005]; 16 for(int i=0;i<m;i++){ 17 vc[(i*i)%m].push_back(i); 18 kk[i]=(i*i)%m; 19 } 20 ll ans=0; 21 for(int i=0;i<m;i++){ 22 for
(int j=0;j<vc[(m-kk[i])%m].size();j++){ 23 ans+=(n/m+((n%m>=i)&&i!=0))*(n/m+((n%m)>=(vc[(m-kk[i])%m][j]%m)&&vc[(m-kk[i])%m][j]!=0)); 24 } 25 } 26 cout << ans<<endl; 27 28 return 0; 29 }