此处有目录↑
HDU-5620 KK's Steel(数学)
http://acm.hdu.edu.cn/showproblem.php?pid=5620
Each test case contains one line including a integer N(1≤N≤1018) ,indicating the length of the steel.
1 6
3Hint1+2+3=6 but 1+2=3 They are all different and cannot make a triangle.
题目大意:对于一条长为N米的钢管,最多可以锯成几根小钢管,使得锯成的钢管互不相等且均不能围成三角形。
官方题解:只考虑最优切割策略:首先肯定是尽量的小即1、2,既要不相等,又不能构成三角形,即每次为当前数列中最大的两项的和,那么,构成的数列为1,2,3,5,8,......这样我们只要求最接近且小于等于N的Fibonacci数和的项数即可。
#include <cstdio>
#include <algorithm>
using namespace std;
int T;
long long f[90],n;
int main() {
f[0]=0;
f[1]=1;
f[2]=2;
for(int i=3;i<90;++i) {
f[i]=f[i-1]+f[i-2];
f[i-2]+=f[i-3];
}
scanf("%d",&T);
while(T--) {
scanf("%I64d",&n);
printf("%d\n",upper_bound(f,f+86,n)-f-1);
}
return 0;
}
HDU-5621 KK's Point(数学)
http://acm.hdu.edu.cn/showproblem.php?pid=5621
For each test case, there are one lines,includes a integer N(2≤N≤105) ,indicating the number of dots of the polygon.
2 3 4
3 5
第一次div1都0题,还是太渣了
数学现在都渣成什么了,什么都不会,找递推还找错了;官方题解的方法还是太巧妙了,没看出来...
官方题解:先撇开边界上的点不管,那么所有的点都是有两条线所构成的,手算得出N=4的时候,能形成一个点,那么,我们只要知道n个点可以构成几个四边形即可,即求C(n,4),最后我们再把边界上的N个点加上,最后的结果是C(n,4)+n
#include <cstdio>
using namespace std;
int T,i,j;
long long n,a[2],b[2];
int main() {
scanf("%d",&T);
while(T--) {
scanf("%I64d",&n);
a[0]=n*(n-1)/2;//计算C(n,4),防止溢出
a[1]=(n-2)*(n-3)/2;
b[0]=2;
b[1]=3;
for(i=0;i<2;++i)
for(j=0;j<2;++j) {
if(a[i]%b[j]==0) {
a[i]/=b[j];
b[j]=1;
}
}
printf("%I64d\n",a[0]*a[1]+n);
}
return 0;
}
HDU-5623 KK's Number(DP)
http://acm.hdu.edu.cn/showproblem.php?pid=5623
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
For each test case, there are two lines,in the first line is a integer N(1≤N≤5∗104) ,the other line has N positive integers(no more than 109 ).
1 3 1 3 1
2HintFirstly KK take 3;and the opponent take 1,1,so the result is 2.
题目大意:这个游戏需要两个人,有N个数,每次KK都会先拿数。每次可以拿任意多个数,直到N个数被拿完。每次获得的得分为取的数中的最小值,KK和对手的策略都是尽可能使得自己的得分减去对手的得分更大。在这样的情况下,最终KK的得分减去对手的得分会是多少?
一点有思维难度的都做不出来,还各种贪心...
#include <cstdio>
#include <algorithm>
using namespace std;
int T,i,j,n,a[50005],dp[50005]={0};
int main() {
scanf("%d",&T);
while(T--) {
scanf("%d",&n);
for(i=1;i<=n;++i)
scanf("%d",a+i);
sort(a+1,a+n+1);
for(i=1;i<=n;++i)
dp[i]=max(dp[i-1],a[i]-dp[i-1]);//对于i,dp[i-1]是i-1个数后手-先手的最大值,a[i]-dp[i-1]则转化为先手-后手的值
printf("%d\n",dp[n]);
}
return 0;
}