AtCoderのABC
次のABCの問題へ
前のABCの問題へ
ABC090-D Remainder Reminder
C#のソース
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static string InputPattern = "InputX";
static List<string> GetInputList()
{
var WillReturn = new List<string>();
if (InputPattern == "Input1") {
WillReturn.Add("5 2");
//7
}
else if (InputPattern == "Input2") {
WillReturn.Add("10 0");
//100
}
else if (InputPattern == "Input3") {
WillReturn.Add("31415 9265");
//287927211
}
else {
string wkStr;
while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
}
return WillReturn;
}
static long mN;
static long mK;
static void Main()
{
List<string> InputList = GetInputList();
long[] wkArr = InputList[0].Split(' ').Select(pX => long.Parse(pX)).ToArray();
mN = wkArr[0];
mK = wkArr[1];
long Answer = 0;
for (long b = 1; b <= mN; b++) {
long NonNaive = DeriveACnt(b);
//long Naive = DeriveACntNaive(b);
//if (NonNaive != Naive) {
// Console.WriteLine("不一致です。b={0}。NonNaive={1}。Naive={2}", b, NonNaive, Naive);
//}
Answer += NonNaive;
}
Console.WriteLine(Answer);
}
// mN以下の正整数(a)で、mod b が mK 以上となる数を返す
static long DeriveACntNaive(long b)
{
long WillReturn = 0;
for (long a = 1; a <= mN; a++) {
if (a % b >= mK) {
WillReturn++;
}
}
return WillReturn;
}
// mN以下の正整数(a)で、mod b が mK 以上となる数を返す
static long DeriveACnt(long b)
{
// a%b は、初項0、末項がb-1、周期bの群数列
// (aを0以上の整数として考える)
// 数列全体の項数
long AllCnt = mN + 1;
// 群の数
long GunCnt = AllCnt / b;
// 最後の群の要素数
long LastGunCnt;
if (AllCnt % b == 0) {
LastGunCnt = b;
}
else {
LastGunCnt = AllCnt % b;
}
long WillReturn = 0;
if (GunCnt >= 1) {
if (mK <= b - 1) {
WillReturn += (b - mK) * GunCnt;
}
}
// 最後の群の端数の処理
if (LastGunCnt < b) {
if (LastGunCnt - 1 >= mK) {
WillReturn += (LastGunCnt - 1 - mK) + 1;
}
}
// aを0以上の整数として考えたので、
// 追加した分の0を解に計上してたら引く
if (0 % b >= mK) {
WillReturn--;
}
return WillReturn;
}
}
解説
6が法の場合は、余りは
0 1 2 3 4 5 0 1 2 3 4 5
で循環する群数列となるので
群数列で考えてます。