日期:2025年7月28日
ZeroJudge 題目連結:b594. A Marvelous Pet
解題想法
這題比較直接的想法,是用兩個指針從小到大掃過一次,變數 low 從 1 到 n-2,變數 high 從 2 到 n-1,區間 [low, high] 之間的加總為 isum。每次更新時有三種可能性:
- 如果 isum = n,答案 ans 加 1,再將整個區間向右平移,isum 減去 low,low 加 1,high 加 1,isum 加上 high。
- 如果 isum > n,isum 減去 low,再將 low 加 1。
- 如果 isum < n,high 加 1,再將 isum 加上 high。
- $mod(2n, k) = 0$
- $tmp = \frac{2n}{k} - k + 1 > 0$
- $mod(tmp, 2) = 0$
- $a = \frac{tmp}{2}, a \leq 1, a+k-1 < n$
Python 程式碼
寫法1,超時。
import sys
def solve(n):
low, high, isum, ans = 1, 2, 3, 0
while low < n-1 and high < n:
if isum == n:
ans += 1
isum -= low
low += 1
high += 1
isum += high
elif isum > n:
isum -= low
low += 1
else:
high += 1
isum += high
return ans
result = []
for line in sys.stdin:
if not line.strip(): continue
n = int(line)
if n == 0: break
ans = solve(n)
result.append(f"{ans:d}\n")
sys.stdout.write("".join(result))
寫法2,使用時間約為 27 ms,記憶體約為 3.3 MB,通過測試。
import sys
for line in sys.stdin:
if not line.strip(): continue
n = int(line)
if n == 0: break
maxn = int(((1+8*n)**0.5 - 1)/2)
ans = 0
for k in range(2, maxn+1):
num = 2*n # 分子
if num%k != 0: continue # 條件1不合
tmp = num//k - k + 1 # 暫存
if tmp <= 0 or tmp%2 == 1: continue # 條件2、3不合
a = tmp//2 # 可能的 a 值
if a >= 1 and a+k-1 < n: ans += 1 # 符合條件4,答案加 1
print(ans)
C++ 程式碼
寫法1,使用時間約為 17 ms,記憶體約為 76 kB,通過測試。
#include <cstdio>
using namespace std;
int solve(int n) {
int low = 1, high = 2, isum = 3, ans = 0;
while(low < n-1 && high < n) {
if (isum == n) {
ans++;
isum -= low;
low++;
high++;
isum += high;
} else if (isum > n) {
isum -= low;
low++;
} else {
high++;
isum += high;
}
}
return ans;
}
int main() {
int n;
while(scanf("%d", &n) != EOF && n != 0) printf("%d\n", solve(n));
return 0;
}
寫法2,使用時間約為 2 ms,記憶體約為 124 kB,通過測試。
#include <cstdio>
#include <cmath>
using namespace std;
int main() {
int n;
while(scanf("%d", &n) != EOF && n != 0) {
int maxn = int((sqrt(1+8*n)-1)/2.0), ans = 0;
for(int k=2; k<=maxn; k++) {
int num = 2*n;
if (num%k != 0) continue;
int tmp = num/k - k + 1;
if (tmp <= 0 || tmp%2 == 1) continue;
int a = tmp/2;
if (a >= 1 && a+k-1 < n) ans++;
}
printf("%d\n", ans);
}
return 0;
}
沒有留言:
張貼留言