B - Power Sequence
题意:给n个数,可以把这n个数任意排列,把数列变成一个等比数列,使第i个数变成c的i次方。可以把任意一个数加一或者减一操作,每次此类操作都要花费 1,问最少花费是多少
题解:因为n>=3,ai<=109,所以公比最大为sqrt(1e9),取1e5使ai不大于1e9.枚举公比
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #include<string> using namespace std; #define max 100010 typedef long long ll; ll a[max]; int main(){ ll n,flag=0,minn=1e18; cin>>n; for(ll i=0;i<n;i++){ cin>>a[i]; } sort(a,a+n); for(ll q=1;q<=1e5;q++){ ll sum=0,m=1; bool flag=1; for(ll j=0;j<n;j++){ if(sum>minn){ flag=0; break; } sum+=abs(a[j]-m); m=m*q; } if(flag){ minn=min(minn,sum); }else{ break; } } cout<<minn<<endl; return 0; }
D - Drinks Choosing
题意:有n个学生和k种饮料,给出n个学生最想喝的饮料,能取 [ n/2 ]组饮料,每组含相同饮料两杯,判断最多有多少学生能喝到他们最喜欢的饮料
题解:如果能拿一组使两杯饮料都有人喝肯定是最好的。把能凑成组的饮料放在sum1里,如果多出来一杯就放在sum2里,如果sum1里的数量大于等于[ n/ 2]*2,那么[ n/ 2]*2个人能喝到自己最喜欢的饮料;如果sum1的数量小于[ n/ 2]*2,那么sum1+([ n/ 2]*2-sum1/2)能喝到自己最喜欢的饮料
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #include<string> using namespace std; typedef long long ll; int a[1010]; int main(){ int n,k,x,temp,sum1=0,sum2=0,ans=0; cin>>n>>k; for(int i=1;i<=n;i++){ cin>>x; a[x]++; } temp=(n+1)/2; for(int i=k;i>=1;i--){ if(a[i]%2==0){ sum1+=a[i]; }else{ sum1+=a[i]-1; sum2+=1; } } if(sum1>=temp*2){ ans=temp*2; }else{ ans=sum1+(temp-sum1/2); } cout<<ans<<endl; return 0; }
E - Sport Mafia
题意:给n次动作和最后的糖果数k。在n次动作里,你可以吃掉一颗或者在盒子里放糖果(放的糖果会比之前多放1块糖),使最后糖果数为k。如果盒子是空的只能在里面放糖;求被吃掉的糖果数.
题解:假设在n次里面有a次是放糖果,b次是吃糖果,则a+b=n;放入的糖果为(1+a)*a/2,吃掉的为b,即(1+a)*a/2+b=k 联立两个式子,求解(一开始没看见放的糖果会比之前多放1块糖,/(ㄒoㄒ)/~~)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #include<string> using namespace std; typedef long long ll; int main(){ ll n,k,sum=0; cin>>n>>k; ll x=sqrt(2*n+2*k+2.25)-1.5; cout<<n-x<<endl; return 0; }
F - Basketball Exercise
题意:有两行身高数,每行n个,取过一个数之后,不能再取和它相邻的数(不包括对角相邻),问身高总和最大为多少
题解:可以先选择第一行队员,也可以选择第二行队员。要让第i次的身高和最大,第i-1次的也应该最大,且第i次可以选择也可以不选择
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<algorithm> #include<iostream> #include<cstdio> #include<cmath> using namespace std; #define MAX 100010 typedef long long ll; ll a[MAX],b[MAX]; ll dp[2][MAX]; int main(){ ll n; cin>>n; for(int i=0;i<n;i++){ cin>>a[i]; } for(int i=0;i<n;i++){ cin>>b[i]; } dp[0][0]=a[0]; dp[1][0]=b[0]; for(int i=1;i<n;i++){ dp[0][i]=max(a[i]+dp[1][i-1],dp[0][i-1]); dp[1][i]=max(b[i]+dp[0][i-1],dp[1][i-1]); } ll end=max(dp[0][n-1],dp[1][n-1]); cout<<end<<endl; return 0; }
7-9 小字辈
题意:给出家族人口总数 N(不超过 100 000 的正整数)把家族成员从 1 到 N 编号。随后第二行给出 N 个编号,其中第 i 个编号对应第 i 位成员的父/母。家谱中辈分最高的老祖宗对应的父/母编号为 -1。首先输出最小的辈分(老祖宗的辈分为 1,以下逐级递增)。然后在第二行按递增顺序输出辈分最小的成员的编号。编号间以一个空格分隔,行首尾不得有多余空格。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<cstdio> #include<cmath> #include<iostream> #include<algorithm> using namespace std; #define MAX 100010 int a[MAX] ,f[MAX]; int find(int x) { if(f[x]){ return f[x]; } f[x]=find(a[x])+1; return f[x]; } int main(){ int n,m,maxx=0,flag=1; cin>>n; for(int i=1;i<=n;i++) { cin>>a[i]; if (a[i]==-1){ f[i]=1; } } for(int j=1;j<=n;j++) { int t=find(j); if(t>maxx){ maxx=t; } } cout<<maxx<<endl; for (int i=1;i<=n;i++) { if (f[i]==maxx){ if(flag){ flag=0; }else{ cout<<" "; } cout<<i; } } return 0; }