1. 程式人生 > >[題解]TopCoder SRM 617 div2 T3 MyVeryLongCake

[題解]TopCoder SRM 617 div2 T3 MyVeryLongCake

題目描述
你有一個很薄的蛋糕。為簡單起見,我們可以認為蛋糕是一維的。蛋糕的長度是n。你正在等一些朋友。在朋友到達之前,你要把蛋糕切成多塊,以便當朋友們到達時,你可以用以下方法將蛋糕分給他們:從蛋糕的開頭開始,首先,你將給你的第一個朋友連續的一部分,然後連續給你的第二個朋友,以此類推。當然,你想要公平。也就是說,你的每個朋友都應該收到相同的蛋糕總量。 (對於不同的朋友,件數可能不同,但他們的長度總和必須相同。)如上所述,你想在朋友到達之前切蛋糕。但是,你不知道會有多少朋友來。你只知道朋友的數量將是小於n的n的因子。你得到了int n。你想要以這樣的方式切蛋糕:對於每個有效數量的朋友,當使用上述方法時,可以給每個朋友提供相同數量的蛋糕。並且把蛋糕分成儘可能少的部分。
題意概述


把一個長度為n(2<=n<=10^9)的區間分成儘可能少的部分,使得對於n的每一個小於n的因子k,可以把區間分成k個連續的部分並且每一部分數值之和相同。輸出最少要分成多少部分。
樣例
Input 1
6
Output 1
4
解釋:分為2 1 1 2

  • 如果有1個朋友,把所有的都給他
  • 如果有2個朋友,把前兩份給第一個 後兩份給第二個
  • 如果有3個朋友,把2給第一個 1 1給第二個 2給第3個

Input 2
3
Output 2
1
解釋:不用切,只可能有1個朋友

Input 3
15
Output 3
7
解釋:分為 3 2 1 3 1 2 3

  • 如果有三個朋友 3 2|1 3 1|2 3
  • 如果有五個朋友 3|2 1|3|1 2|3

Input 4
1000000000
Output 4
600000000

Input 5
577007436
Output 5
384671628
分析
搞了半天最後才發現原來是個尤拉函式TAT。

把蛋糕看成一個n*1的矩形
設a * b=n,那麼,對於每一個i(1<=i < b),第a * i個方格後面會被切一刀,也就是說,對於每一個k(1<=k< n),如果k和n不互質,第k個方格後面要被切一刀。

由於n以內(不包括n)的數中與n互質的數有

(n)" role="presentation" style="position: relative;"> φ ( n ) 個,並且最後一個方格後面不需要切,所以有 n φ ( n ) 1 個方格後面需要切一刀,最終把蛋糕劃分成了 n φ ( n ) 個部分
程式碼

//tc is healthy, just do it
#include <bits/stdc++.h>
using namespace std;

class MyVeryLongCake {
public:
    int cut( int n );
};

int euler(int x){
    int ans=x;
    for(int i=2;i*i<=x;i++){
        if(x%i==0){
            ans-=ans/i;
            while(x%i==0)x/=i;
        }
    }
    if(x>1)ans-=ans/x;
    return ans;
}

int MyVeryLongCake::cut(int n) {
    return n-euler(n);
}