問題 A: 分火腿
題目描述
小月⾔要過四歲⽣日了,她的媽媽爲她準備了n根⽕腿,她想將這些⽕腿均分給m位小朋友,所以她可能需要切⽕腿。爲了省事,小月⾔想切最少的⼑數,使這n根⽕腿分成均等的m份。請問最少要切⼏⼑?
輸入
第⼀⾏⼀個整數T,表示有T組數據。
接下來T組數據,每組共⼀⾏,有兩個數字n,m。
輸出
每組數據⼀⾏,輸出最少要切的⼑數。
樣例輸入 Copy
2
2 6
6 2
樣例輸出 Copy
4
0
思路:
一開始題目沒說2根香腸分3份只要切2刀,wa了,後來考慮了這種情況,找規律可得解;
ll gcd(ll a,ll b)
{
if(b==0) return a;
else return gcd(b,a%b);
}
int main()
{
int n;cin>>n;
while(n--)
{
ll x,y;
cin>>x>>y;
if(y==0||x%y==0) cout<<0<<endl;
else if(y%x==0)
{
ll z=y/gcd(x,y);
cout<<(z-1)*x<<endl;
}
else
cout<<y-gcd(x,y)<<endl;
}
return 0;
}
問題 B: 工資
題目描述
n+e在暑假參加了打零⼯的活動,這個活動分爲n個⼯作日,每個⼯作日的⼯資爲Vi。有m個結算⼯錢的時間,n+e可以自由安排這些時間,也就是說什麼時候拿錢,老闆說的不算,n+e纔有發⾔權!(因爲n+e是⼟豪,他是老闆的老闆)
n+e不喜歡身上⼀次性有太多的錢,於是他想安排⼀下拿錢的時間,使他⼀次性拿的錢中最⼤的那次的最小。(最後⼀天⼀定要領錢)
輸入
第⼀⾏2個數n,m
接下來n⾏,每⾏⼀個數,代表Vi
輸出
輸出⼀⾏⼀個整數,表示最小的最⼤錢數。
樣例輸入 Copy
7 5
100
400
300
100
500
101
400
樣例輸出 Copy
500
提示
100 400//300 100//500//101//400// ”//” 表示 n+e 要去拿錢。
對於20%的數據,1<=n<=20
對於另20%的數據,1≤n≤50,Vi的和不超過1000
對於100%的數據,1≤n≤100000,m≤n,Vi≤100000
思路:
二分答案ans,判斷mid是否符合judge函數的判斷,符合判斷則滿足分組要求,可以將 r 減小,否則將 l 增大。
int n,m;
ll a[100005];///用long long
bool judge(ll mid)
{
int cnt=0;
ll ret=0;
for(int i=1;i<=n;i++)
{
if(ret+a[i]>mid)
{
ret=a[i];
cnt++;
}
else ret+=a[i];
if(cnt>=m || ret>mid)///有多於m個分組是大於mid的,則非法
return false; ///或者是其中一個數ret大於mid,也非法
}
if(cnt<m) return true;
return false;
}
int main()
{
cin>>n>>m;
ll ans,minn=1000000,maxn=0;
for(int i=1;i<=n;i++)
{
cin>>a[i];
maxn+=a[i];
minn=min(minn,a[i]);
}
while(minn<maxn)
{
ll mid=(minn+maxn)/2;
if(judge(mid)) maxn=mid;
else minn=mid+1;
}
cout<<minn<<endl;
}
問題 C: 公約數
題目描述
話說CD比較⽋扁,他表示在課室的日⼦沒有教主在旁邊打他的日⼦太寂寞了,所以這⼀晚,他終於來到了電腦室被打。由於CD是⼤家的寵物,於是⼤家都來打CD了。
電腦室裏有n個⼈,第i個⼈希望打CD ai下。但是太多⼈打CD,他又會不爽,於是他規定只能有K個⼈打到他,並且爲了公平起見,最終K個⼈打他的次數都必須是相同的,CD規定這個次數就是這K個⼈希望打他的次數的最⼤公約數。爲什麼是最⼤公約數呢?因爲他覺得被打的次數是GCD的話他纔會變成Glad CD。
之前說了,CD比較⽋扁,於是CD希望,K個⼈打他的次數的和最⼤。你能告訴他他最後總共會被打多少下麼?
輸入
第⼀⾏兩個正整數n,k。
第⼆⾏n個正整數,表示每個⼈希望打CD多少下。
輸出
輸出⼀個正整數表示CD會被打多少下。
樣例輸入 Copy
3 1
1 2 3
樣例輸出 Copy
3
提示
對於30%的數據,保證k≤n≤20。
對於50%的數據,保證輸⼊中所有數小於5000。
對於100%的數據,保證輸⼊中所有數小於500000,k≤n。
思路:暴力枚舉: i 從a[i]_max開始枚舉到1,查詢是否有大於等於k個數數是i的倍數,若有,則i是最大公約數。
int n;
ll k;
int visit[500005];
int main()
{
cin>>n>>k;
int maxn=0;
for(int i=1;i<=n;i++)
{
int x;
scanf("%d",&x);visit[x]++;
maxn=max(maxn,x);
}
for(int i=maxn;i>=1;i--)
{
int cnt=0;
for(int j=i;j<=maxn;j+=i)///查詢是否存在i的倍數
{
if(visit[j])cnt+=visit[j];///存在,則計算有多少個
if(cnt>=k) break;
}
if(cnt>=k)
{
printf("%lld",i*k);///cout會出錯
break;
}
}
}