hihocoder 1298
描述
小Hi和小Ho有時候會用密碼寫信來互相聯繫,他們用了一個很大的數當做密鑰。小Hi和小Ho約定了一個區間[L,R],每次小Hi和小Ho會選擇其中的一個數作爲密鑰。
小Hi:小Ho,這次我們選[L,R]中的一個數K。
小Ho:恩,小Hi,這個K是多少啊?
小Hi:這個K嘛,不如這一次小Ho你自己想辦法算一算怎麼樣?我這次選擇的K滿足這樣一個條件:
假設φ(n)表示1..n-1中與n互質的數的個數。對於[L,R]中的任意一個除K以外的整數y,滿足φ(K)≤φ(y)且φ(K)=φ(y)時,K<y。
也即是K是[L,R]中φ(n)最小並且值也最小的數。
小Ho:噫,要我自己算麼?
小Hi:沒錯!
小Ho:好吧,讓我想一想啊。
<幾分鐘之後...>
小Ho:啊,不行了。。感覺好難算啊。
小Hi:沒有那麼難吧,小Ho你是怎麼算的?
小Ho:我從枚舉每一個L,R的數i,然後利用輾轉相除法去計算[1,i]中和i互質的數的個數。但每計算一個數都要花好長的時間。
小Hi:你這樣做的話,時間複雜度就很高了。不妨告訴你一個巧妙的算法吧:
輸入
第1行:2個正整數, L,R,2≤L≤R≤5,000,000。
輸出
第1行:1個整數,表示滿足要求的數字K
樣例輸入
- 4 6
樣例輸出
- 4
Solution
歐拉函數的板子題
Code
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <stack>
#include <map>
#include <vector>
#include <queue>
#define LL long long
#define L 5000010
using namespace std;
int l, r, phi[L], minx = L, ans;
int main() {
scanf("%d %d", &l, &r);
phi[1] = 1;
for (int i = 2; i <= r; ++i)
if (!phi[i])
for (int j = i; j <= r; j += i) {
if (!phi[j]) phi[j] = j;
phi[j] = phi[j] / i * (i - 1);
}
for (int i = l; i <= r; ++i)
if (phi[i] && phi[i] < minx) minx = phi[i], ans = i;
printf("%d\n", ans);
return 0;
}
Summary
注意找最小phi值的時候minx要賦初值