B. Divide Candies(数学 + 思维)

文章描述了一个在n×n棋盘上的跳棋游戏,其中每个格子含有不同数量的糖果,基于古老寓言,主角Arkady想平均分配糖果给m个朋友。问题转化为找到可以被m整除的糖果组合。解决方案涉及计算满足条件的格子集合,然后根据棋盘的形状计算总的组合数。
摘要由CSDN通过智能技术生成

Problem - B - Codeforces

Arkady和他的朋友们喜欢在一个n × n的棋盘上玩跳棋。这个棋盘的行和列从1到n编号。
他的朋友们最近赢了一场比赛,所以Actady想用一些糖果来取悦他们。记得一则古老寓言(但不记得寓意)》,Arlady想给他的朋友们每个格子一个糖果组:第(1.j)个格子的糖果组将有(+j2)种不同类型的糖果。
有m个值得获得礼物的朋友。有多少个n × n的糖果组可以被平均地分成m 部分而不切碎任何一个糖果?请注意,每个组必须独立分割,因为不同组中的糖果类型不同。
输入
仅一行包含两个整数n和m (1<n<109,1<m <1000)——场地的大小和要将组件分成的部分数。
输出
输出单个整数——可以平均分成的组数。

Examples

input

Copy

3 3

output

Copy

1

input

Copy

6 5

output

Copy

13

input

Copy

1000000000 1

output

Copy

1000000000000000000

在第一个例子中,只有单元格(3,3)的集合可以被平均分割(32+32=18,可被m=3整除)。

在第二个例子中,以下单元格的集合可以被平均分割:

(1,2)和(2,1),因为12+22=5,可以被5整除; (1,3)和(3,1); (2,4)和(4,2); (2,6)和(6,2); (3,4)和(4,3); (3,6)和(6,3); (5,5)。

在第三个例子中,所有单元格中的集合都可以被平均分割,因为m=1。

题解:

由于m只有1000,所有我们要从m着手考虑,

(i*i + j*j)%m == 0

(i%m*i%m + j%m*j%m) == 0

我们可以把n*n的块分成很多,m*m的小块,类似这样

接着我们算这四块的面积即可 

 

#include <cstdio>
#include <cstring>
#include <algorithm>
#include<iostream>
#include<vector>
#include<set>
#include<map>
#include<cmath>
#include<queue>
using namespace std;
typedef long long ll;
#define int long long
typedef pair<int,int> PII;
int mod = 998244353;
int n;
int a[505];
void solve()
{
	int n,m;
	cin >> n >> m;
	int cnt = 0;
	for(int i = 1;i <= m;i++)
	{
		for(int j = 1;j <= m;j++)
		{
			int x = i*i + j*j;
			if(x% m == 0)
			cnt++;//m*m小块的符合答案数量
		}
	}
	int ans = 0;
	ans += (n/m)*(n/m)*cnt;//多少个m*m的小块
	cnt = 0;
	for(int i = n - n%m + 1;i <= n;i++)
	{
		for(int j = 1;j <= m;j++)
		{
			int x = i*i + j*j;
			if(x%m == 0)
			cnt++;左边长条的符合答案数量
		}
	}
	ans += n/m*cnt*2;//由于有两个长块
	cnt = 0;
	for(int i = n - n%m + 1;i <= n;i++)
	{
		for(int j = n - n%m + 1;j <= n;j++)
		{
			int x = i*i + j *j;
			if(x%m == 0)
			cnt++;//右上方块的答案
		}
	}
	cout << ans + cnt;
}
signed main()
{
//	ios::sync_with_stdio(0 );
//	cin.tie(0);cout.tie(0);
	int t = 1;
//	cin >> t;
	while(t--)
	{
		solve(); 
	}
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值