http://acm.hdu.edu.cn/showproblem.php?pid=5615
2 1 6 5 1 6 4
YES NOHintThe first case turn (x+1)(x+5)=x^2+6∗x+5
题目大意:判断 ax^2+bx+c能都分解成(px+k)(qx+m)的形式,要求p,q,k,m均为正整数
直接无视正整数三个字,被HACK了。
不过终测后都对了。。。
也没注意a,b,c的范围,由于a,b,c均为正整数,所以若能分解因式,则系数均为正整数
#include <cstdio> #include <cmath> using namespace std; long long a,b,c,T,x,xx; int main() { scanf("%I64d",&T); while(T--) { scanf("%I64d%I64d%I64d",&a,&b,&c); x=b*b-4*a*c; if(x>=0) { xx=sqrt(x); if(xx*xx==x) { printf("YES\n"); continue; } } printf("NO\n"); } return 0; }
http://acm.hdu.edu.cn/showproblem.php?pid=5616
1 2 1 4 3 2 4 5
NO YES YESHintFor the Case 1:Put the 4 weight alone For the Case 2:Put the 4 weight and 1 weight on both side
题目大意:有n个砝码和一个没有刻度的天平,砝码可以放在任意一侧,问最后能否称出k的物品
先考虑只在只有砝码的一侧放置,有两种状态,当前砝码放或不放,可以用dp解决
当i可以称出t时,i+w也可以称出
把所有物体一侧的砝码可以等效成负的砝码加在只有砝码的一侧,这样就把物体和砝码分开了
因此可能存在“负”的质量,所以可以全部加上一个常数,防止越界
由于当前砝码的更新会影响后续的更新,所以需要用二维数组表示
#include <cstdio> #include <cstring> using namespace std; int T,n,m,w,k,i,j,sum,mn,x; bool dp[2][4105]; const int ORD=2055; int main() { scanf("%d",&T); while(T--) { scanf("%d",&n); sum=0; mn=105; memset(dp,false,sizeof(dp)); dp[0][ORD]=true; for(i=0;i<n;++i) { scanf("%d",&w); sum+=w; for(j=0;j<4005;++j) if(dp[i&1][j])//给所有砝码一侧的重量加上一个常数,不必再考虑越界问题 dp[(i+1)&1][j]=dp[(i+1)&1][j+w]=dp[(i+1)&1][j-w]=true; } scanf("%d",&m); while(m--) { scanf("%d",&k); printf("%s\n",0<=k&&k<=sum&&dp[n&1][k+ORD]?"YES":"NO"); } } return 0; }
———————————————————万年2题的旅游分割线———————————————————
http://acm.hdu.edu.cn/showproblem.php?pid=5617
1 4 ABCD BEFE CDEB GCBA
12Hintthere are 1 solutions is"ABCDCBA" there are 1 solutions is"ABCGCBA" there are 4 solutions is"ABEDEBA" there are 6 solutions is"ABEFEBA"
题目大意:有一个n*n的迷宫,每个点有一个大写字母,从左上角走到右下角,每次只能往下或往右走,求有多少种路径所得字符串是回文的
结果很大,应该往dp想
由于起点和终点确定,所以可以同时从起点和终点走,设状态为dp[x1][y1][x2][y2],初始若mp[1][1]==mp[n][n],则dp[1][1][n][n]为1,否则直接输出0
枚举合法的位置,若mp[x1][y1]==mp[x2][y2],则进行状态转移
dp[x1][y1][x2][y2]可由dp[x1-1][y1][x2+1][y2],dp[x1-1][y1][x2][y2+1],dp[x1][y1-1][x2+1][y2],dp[x1][y1-1][x2][y2+1]转移而来
由于这样会MLE,所一可以用dp[step][x1][x2]表示状态,step表示目前是第step步,则可求出y1和y2,仍会MLE;又当前步状态只与上一步状态有关,所以可以用滚动数组
#include <cstdio> #include <cstring> using namespace std; int T,n,x1,x2,y1,y2,step,cur,ans; int dp[2][505][505]; char mp[505][505]; int main() { scanf("%d",&T); while(T--) { scanf("%d",&n); for(x1=1;x1<=n;++x1) scanf("%s",mp[x1]+1); if(mp[1][1]!=mp[n][n]) { printf("0\n"); continue; } memset(dp,0,sizeof(dp)); dp[0][1][n]=1; cur=ans=0; for(step=1;step<n;++step) { cur^=1; memset(dp[cur],0,sizeof(dp[cur])); for(x1=1;x1<=n&&x1<=step+1;++x1) { y1=step-x1+2; for(x2=n;x2>0&&x2>=n-step;--x2) { y2=2*n-x2-step; if(mp[x1][y1]==mp[x2][y2]) dp[cur][x1][x2]=(dp[cur^1][x1][x2]+dp[cur^1][x1-1][x2]+dp[cur^1][x1][x2+1]+dp[cur^1][x1-1][x2+1])%5201314; } } } for(x1=1;x1<=n;++x1) ans=(ans+dp[cur][x1][x1])%5201314; printf("%d\n",ans); } return 0; }