通过这场比赛再次认识到自己的菜,被大佬们吊着锤。。。开场的一个小时节奏还算不错,先过了1004,1009也有思路。接着,服务器就炸了。。。交上去的一发也WA了,比赛中途居然在一直刷网页。。。还好1009把bug找出来A掉了。。。可是1003还是找不出规律啊,1010的dp还是不会优化啊,1001贪心也贪错了啊。。。
不说了,总结起来还是自己太弱了。。。(只能靠赛后补题来防止自己更菜了。。。)
-------------------------------------------------------------------------------------------------------------------------------------------------------
1004 - Find Integer(hdu6441)
题意:找到一组b和c,使得a^n+b^n=c^n。没有输出-1,-1。
这题看一眼应该都想到费马大定理了。n>=3时是无解的。那么只看n=1和n=2即可,n=1是取b=1,c=a+1即可。关键在于n=2时,要想到勾股数的公式(1)当a为大于1的奇数2n+1时,b=2n^2+2n, c=2n^2 +2n+1(2)当a为大于4的偶数2n时,b=n^2-1, c=n^2+1
这个百度就可以了(逃)
代码:
#include
#include
#include
#include
#include
#include
#include
1009 Tree and Permutation(hdu6446)
题意:从给出的序列的一个端点到另一个端点的费用即为s(i),求所有序列的全排列s(i)的和
这题是队友想出来的,Orz果爷。。。
通过观察可以发现只要计算这个序列中任意两点距离的总和 乘上 2(n-1)f(n-2), 其中f(i)代表i的阶乘。
后面是怎么得到的呢?如(1 3)和(3 1)算了两次,所以乘2。后面的可以将此时选出来的两个数看成一个整体,一个组合数就搞定了(很像高中的排列组合题)。。。
那么任意两点间距离怎么算呢?其实对边统计就行了,对每条边而言,经过这条边的总次数就是这条边两边点数的乘积。所以这道题其实1遍dfs即可。。。
代码:
#include
#include
#include
#include
#include
#include
#include
1003 Dream (hdu6440)
题意:不说了(哭),场上读了一小时也不懂,英语弱菜。。。
这题结论好简单啊,就是在加法和乘法基础上取个模就好了。。。
不过你能想到?(大佬请无视)
弱弱的我还是不会证。。。
代码:
#include
#include
#include
using namespace std;
int main()
{
int t,p;
scanf("%d",&t);
while(t--)
{
scanf("%d",&p);
for(int i=0;i
1010 YJJ's Salesman (hdu6447)
题意:从(0,0)出发到(1e9,1e9),途中不走回头路且只能向下,右,右下走,且只有想右下走时能拿钱,求最多拿多少钱
dp转移很好像,很明显TLE+MLE。首先必然离散化,由于我太弱了,二维的离散化之前没怎么写过,比赛时很生疏。。。
离散完后思路还是明显的,j表示当前所在列(这里需要从右往左,从上往下扫,和01背包的优化相似)f[j]代表当前列最大值,即f[j]=max(f[1]~f[i]+v[num],f[j])(1=
看到了维护区间最大值,线段树或BIT搞一下就可以了
代码:
#include
#include
#include
#include
#include
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
using namespace std;
typedef long long ll;
const int MAXN=1e5+10;
typedef struct
{
ll x;
ll y;
ll v;
} Node;
Node node[MAXN];
ll nx[MAXN];
ll ny[MAXN];
ll MAX[MAXN<<2];
ll Max;
int tx,ty;
int t,n;
bool cmp(Node a,Node b)
{
if(a.x==b.x)
return a.y>b.y;
else
return a.x> 1;
if (p <= m) update(p , sc , lson);
else update(p , sc , rson);
PushUP(rt);
}
ll query(int L,int R,int l,int r,int rt) {
if (L <= l && r <= R) {
return MAX[rt];
}
int m = (l + r) >> 1;
ll ret = 0;
if (L <= m) ret = max(ret , query(L , R , lson));
if (R > m) ret = max(ret , query(L , R , rson));
return ret;
}
int main()
{
int cntx,cnty;
ll tem,ans;
scanf("%d",&t);
while(t--)
{
cntx=cnty=0;
memset(MAX,0,sizeof(MAX));
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%lld%lld%lld",&node[i].x,&node[i].y,&node[i].v);
nx[++cntx]=node[i].x;
ny[++cnty]=node[i].y;
}
sort(nx+1,nx+1+cntx);
sort(ny+1,ny+1+cnty);
tx=unique(nx+1,nx+cntx+1)-(nx+1);
ty=unique(ny+1,ny+cnty+1)-(ny+1);
for(int i=1;i<=n;i++)
{
node[i].x=lower_bound(nx+1,nx+cntx+1,node[i].x)-nx;
node[i].y=lower_bound(ny+1,ny+cnty+1,node[i].y)-ny;
}
sort(node+1,node+1+n,cmp);
printf("%d %d\n",tx,ty);
int y;
ans=0;
for(int i=1;i<=n;i++)
{
y=node[i].y;
if(y!=1)
{
Max=query(y,y,1,n,1);
tem=max(Max,query(1,y-1,1,n,1)+node[i].v);
update(y,tem,1,n,1);
ans=max(ans,tem);
}
else
{
Max=query(y,y,1,n,1);
tem=node[i].v;
update(y,tem,1,n,1);
ans=max(ans,tem);
}
}
printf("%lld\n",ans);
}
return 0;
}
1001 Buy and Resell (hdu6438)
思路:每个地方有一个价格,可以在每个地方选择买,卖,或不买不卖。同时可携带多个商品,初始钱无限,问最多赚多少钱。
和 http://codeforces.com/problemset/problem/867/E差不多,
可以看看这篇题解
https://blog.csdn.net/qq_28954601/article/details/78146932
唯一不同的是这题要求交换次数最小。其实也好像,比如1 -> 2 ->5 -> 10,中间多算了2和5,那么把他们减掉就可以了。也就是对于既卖又买的点减掉即可。。。
代码:
#include
#include
#include
#include
#include
其实还想补个1007,但由于我太弱了,等过两天再补,待更。。。