砝码称重
问题描述
你有一架天平和 N 个砝码,这 N 个砝码重量依次是 W1,W2,⋅⋅⋅,WN。
请你计算一共可以称出多少种不同的重量? 注意砝码可以放在天平两边。
输入格式
输入的第一行包含一个整数 N。
第二行包含 N 个整数 W1,W2,W3,⋅⋅⋅,WN。
输出格式
输出一个整数代表答案。
样例输入
3
1 4 6
样例输出
10
样例说明
能称出的 10 种重量是:1、2、3、4、5、6、7、9、10、11
1 = 1;
2=6−4(天平一边放 6,另一边放 4);
3 = 4 − 1;
4 = 4;
5 = 6 − 1;
6 = 6;
7 = 1 + 6;
9 = 4 + 6 − 1;
10 = 4 + 6;
11 = 1 + 4 + 6。
评测用例规模与约定
对于 50%的评测用例,1≤N≤15。
对于所有评测用例,1≤N≤100,N个砝码总重不超过 100000。
说明:dp[0][0]=1表示:0个砝码(=1)能称出重量0
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
int dp[105][100000]={0},n,w[105],sum=0,ans=0;
cin>>n;
for(int i=1;i<=n;i++){
cin>>w[i];
sum+=w[i];//砝码总重量,称不出比总重量还重的重量
}
dp[0][0]=1;
for(int i=1;i<=n;i++){
for(int j=0;j<=sum;j++){
//重量没有负数,因此用绝对值表示(例如:2-4=-2取绝对值后相当于能称出质量2)
dp[i][j]=max(dp[i-1][j],max(dp[i-1][j+w[i]],dp[i-1][abs(j-w[i])]));
//dp[0][j](j>0)=0,dp[i][0]=1,若dp[i-1][j]=1,则dp[i][j]=1;否则就加入
}
}
for(int i=1;i<=sum;i++){//重量0不算一种情况
if(dp[n][i]) ans++;//用n个砝码能(dp=1)否(dp=0)称出重量i
}
cout<<ans<<endl;
return 0;
}
杨辉三角形
题目描述
下面的图形是著名的杨辉三角形:
如果我们按从上到下、从左到右的顺序把所有数排成一列,可以得到如下数列:1,1,1,1,2,1,1,3,3,1,1,4,6,4,1,⋯
给定一个正整数 N,请你输出数列中第一次出现 N 是在第几个数?
输入描述
输入一个整数 N。
输出描述
输出一个整数代表答案。
示例 1
输入
6
输出
13
评测用例规模与约定
对于 20% 的评测用例,1≤N≤10; 对于所有评测用例, 1≤N≤1e9。
!!可以发现第一次出现的数一定都在左边!!
#include <iostream>
using namespace std;
//杨辉三角
typedef long long ll;
ll n;//n<=1e9
ll C(ll a,ll b){//求组合数Cab
ll res=1;//res也可能很大!!!
for(ll i=a,j=1;j<=b;i--,j++){
res=res*i/j;
if(res>n) return res;
}
return res;
}
int main()
{
cin>>n;
for(int k=16;k>=0;k--){//从第16列开始二分查找,先找所在列
ll l=2*k,r=max(n,l),mid;//mid:所在行
while(l<=r){
mid=(r+l)/2;
ll c=C(mid,k);
if(c==n) break;
else if(c>n) r=mid-1;
else l=mid+1;
}
if(C(mid,k)==n){
cout<<(mid+1)*mid/2+k+1<<endl;//第0行1个数,开始
break;
}
}
// n=1e9;
// for(ll i=1;;i++){
// if(C(2*i,i)>n){
// cout<<i<<endl;
// break;
// }
// }算出n最多出现在第16列
return 0;
}
坑坑坑:最好这里面数据类型都用long long,要不连哪里错了都找不到!!!