hdu1060 Leftmost Digit
题意:
计算nn的第一位数字
思路:
把nn转化为科学计数法nn=a * 10x,其中a是浮点数,x是整数。我们要的答案就是(int)a。
现在想办法计算这个a:
左右同时取以10为底的对数,则式子变为:nlg(n)=lg(a)+x。
发现只需要知道x的值就能计算出a,因为x是科学计数法10的幂次,所以x=lg(nn)向下取整,即x=nlg(n)向下取整。
然后就能计算出a=10lg(nlg(n)-x)。
code:
#include<bits/stdc++.h>
using namespace std;
#define int long long
signed main(){
int T;
cin>>T;
while(T--){
int n;
cin>>n;
int x=n*log10(n);
int ans=pow(10,n*log10(n)-x);
cout<<ans<<endl;
}
return 0;
}
bzoj1045: [HAOI2008] 糖果传递
题意:
有n个小朋友坐成一圈,每人有ai个糖果。每人只能给左右两人传递糖果。每人每次传递一个糖果代价为1。
求使所有人获得均等糖果的最小代价。
思路:
设f[i]是i给i+1的糖果数量,ave是糖果均值
则:
f[2]=f[1]+a[2]-ave;
f[3]=f[2]+a[3]-ave=f[1]+a[2]+a[3]-2*ave
...
f[i]=f[1]+(a[2]+...a[i])-(i-1)*ave;
设s[i]=(i-1)*ave-(a[2]+...a[i]);
则f[i]=k-s[i];(必须要转化成这样的减法形式,下面才能取中位数)
最后的答案是|f[1]|+|f[2]|...+|f[n]|
|f[i]|=|k-s[i]|,而|k-s[i]|类似坐标系x轴上某一点k到其他所有点s[i]的距离和
我们知道要使得|k-s[i]|最小,k应该是s[i]中的中位数
知道k就可以直接计算答案f[],然后计算出答案了
code:
#include<bits/stdc++.h>
using namespace std;
const int maxm=1e6+5;
int a[maxm];
int s[maxm];
signed main(){
int n;
cin>>n;
int sum=0;
for(int i=1;i<=n;i++){
cin>>a[i];
sum+=a[i];
}
int ave=sum/n;
for(int i=2;i<=n;i++){
s[i]=s[i-1]+ave-a[i];
}
sort(s+1,s+1+n);
int ans=0;
for(int i=1;i<=n;i++){
ans+=abs(s[n/2]-s[i]);
}
cout<<ans<<endl;
return 0;
}
CodeForces1328 F. Make k Equal
题意:
给一个长度为n的数组a,和一个整数k,
现在你能进行两种操作:
1.把数组中最大的数减1
2.把数组中最小的数加1
你可以进行操作无限次,问最少进行多少次操作之后可以使得数组中有k个相同的数。
思路:
最后相同的数一定是原数组中已经存在的数
假设这个相同的数为x,
如果要把至少一个小于x的数变为x,那么一定要把所有小于x的数先变为x-1,
如果要吧至少一个大于x的数变为x,那么一定要把所有大于x的数先变为x+1,
先对a(i)排序+去重,记得记录每个数出现的次数
预处理出把小于a(i)的数全部变为a(i)-1和把大于a(i)的数全部变为a(i)+1的花费
枚举最后相同的数a(i),对于每个a(i)分类讨论:
如果将小于(或者大于)a(i)的若干数变为a(i)能够凑到k个,计算一下然后取min更新答案
如果将小于(或者大于)a(i)的数全部变为a(i)还是不够,那么就用另外一遍的凑,计算一下然后min更新答案。
code:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxm=2e5+5;
map<int,int>mark;
int l[maxm];//l[i]表示i左边全部a[i]-1的花费
int r[maxm];//r[i]表示i右边全部a[i]+1的花费
int lc[maxm];//lc[i]表示i以及左边一共多少个数
int rc[maxm];//rc[i]表示i以及右边一共多少个数
int cnt[maxm];//cnt[i]表示a[i]的个数
int sum[maxm];//cnt[i]*a[i]的前缀和
int a[maxm];
signed main(){
int n,k;
cin>>n>>k;
for(int i=1;i<=n;i++){
cin>>a[i];
mark[a[i]]++;
}
sort(a+1,a+1+n);
n=unique(a+1,a+1+n)-a-1;
for(int i=1;i<=n;i++){//cnt[]
cnt[i]=mark[a[i]];
}
for(int i=1;i<=n;i++){//lc[]
lc[i]=lc[i-1]+cnt[i];
}
for(int i=n;i>=1;i--){//rc[]
rc[i]=rc[i+1]+cnt[i];
}
for(int i=1;i<=n;i++){//sum[]
sum[i]=sum[i-1]+cnt[i]*a[i];
}
for(int i=1;i<=n;i++){//l[]
l[i]=lc[i-1]*(a[i]-1)-sum[i-1];
}
for(int i=n;i>=1;i--){//r[]
r[i]=(sum[n]-sum[i])-rc[i+1]*(a[i]+1);
}
int ans=sum[n];
for(int i=1;i<=n;i++){//计算答案
if(cnt[i]>=k){//已经有k个了
ans=0;
break;
}
if(lc[i-1]>=k-cnt[i]){//左边够
ans=min(ans,l[i]+k-cnt[i]);
}else{//左边不够
ans=min(ans,l[i]+lc[i]+(k-cnt[i]-lc[i])+r[i]);
}
if(rc[i+1]>=k-cnt[i]){//右边够
ans=min(ans,r[i]+k-cnt[i]);
}else{//右边不够
ans=min(ans,r[i]+rc[i]+(k-cnt[i]-rc[i])+l[i]);
}
}
cout<<ans<<endl;
return 0;
}