真是伤心。。。这场比赛我两个题在20min中全部做完,全部因为忘了特判导致fst,我是sb。。。
http://acm.hdu.edu.cn/showproblem.php?pid=5186
最水的题,纯比手速,结果我为了抢时间忘记特判,最后fst掉了。。。
要特判的情况就是输出的答案为0的情况。。。
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#define MAXN 500
using namespace std;
char s[MAXN];
int ans[MAXN],ss[MAXN];
int main()
{
int n,B;
while(scanf("%d%d",&n,&B)!=EOF)
{
memset(ans,0,sizeof(ans));
for(int i=1;i<=n;i++)
{
scanf("%s",s+1);
int len=strlen(s+1);
for(int i=1;i<=len;i++)
{
if(s[len-i+1]>='0'&&s[len-i+1]<='9')
ss[i]=s[len-i+1]-'0';
else
ss[i]=s[len-i+1]-'a'+10;
}
for(int i=1;i<=len;i++)
ans[i]=(ans[i]+ss[i])%B;
}
int tmp=MAXN-1;
while(!ans[tmp]&&tmp>=1) tmp--;
if(!tmp) printf("0"); //坑爆了!!!
for(int i=tmp;i>=1;i--)
{
if(ans[i]<=9) printf("%d",ans[i]);
else printf("%c",ans[i]-10+'a');
}
printf("\n");
}
return 0;
}
还是特判, n>1 时最终答案为 2n−2 , n=1 时显然答案为1。。。
但是仅仅这些还不够,由于题目中所有数的范围在1e18范围内,做乘法时可能爆long long,因此要用快速加,然后如果 n=1,p=1 时答案为0,显然 n=1 时只输出 1 是错的,要输出1 mod p
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
using namespace std;
typedef long long int LL;
LL mul(LL a,LL b,LL p)
{
LL ans=0;
while(b)
{
if(b&1) ans=(ans+a)%p;
a=(a+a)%p;
b>>=1;
}
return ans;
}
LL fastPow(LL base,LL pow,LL p)
{
LL ans=1;
while(pow)
{
if(pow&1) ans=mul(ans,base,p);
base=mul(base,base,p);
pow>>=1;
}
return ans;
}
int main()
{
LL n,p;
while(scanf("%I64d%I64d",&n,&p)!=EOF)
{
if(n==1)
{
printf("%I64d\n",1%p);
continue;
}
LL ans=fastPow(2,n,p);
ans=(ans-2+p)%p;
printf("%I64d\n",ans);
}
return 0;
}
标准做法是DP。。。不是很好想。。。。
这里我用的做法是参考别人的一种非常巧妙的二分+深搜。我们可以先按照每个题目最早可以开始做的时刻( li−ti )升序排序,显然所有题目权值之和 <w 则无解。而且显然最少做完所有题目的时间是可以二分出来的,因此我们二分最终需要的最少时间,从最后一个题往前倒着搜,爆枚每个题是否选择做了(如果这个题最早可以做出来的时间在当前时刻之前,而且当前的时刻足够这个题做出来的话,这个题就可以选择做,否则一定不能做),这样的方法比较简单,而且正确性比较显然。
当然,这样的爆搜有很多可以剪枝的地方,我们可以预处理出排序后的题目权值的前缀和,如果在搜索过程中发现,如果1~当前题都做出来,仍然做不到w分,那么说明当前的DFS状态显然是无解的,直接退出。
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#define MAXN 100
using namespace std;
typedef long long int LL;
struct Prob
{
int t,l;
LL v;
}probs[MAXN];
LL sum[MAXN];
int n,w;
bool cmp(Prob a,Prob b)
{
return a.l-a.t<b.l-b.t; //!!!!!!!!
}
bool DFS(int x,int t,LL solved) //zuo le x ti,shi jian yong le time,zuo chu le solved fen
{
if(solved>=w) return true;
if(x<=1) return false;
if(solved+sum[x-1]<w) return false;
if(probs[x-1].t<=t&&probs[x-1].l<=t)
if(DFS(x-1,t-probs[x-1].t,solved+probs[x-1].v))
return true;
if(DFS(x-1,t,solved))
return true;
return false;
}
int main()
{
while(scanf("%d%d",&n,&w)!=EOF)
{
//memset(used,false,sizeof(used));
for(int i=1;i<=n;i++)
scanf("%d%lld%d",&probs[i].t,&probs[i].v,&probs[i].l);
sort(probs+1,probs+n+1,cmp);
for(int i=1;i<=n;i++) sum[i]=sum[i-1]+probs[i].v;
int lowerBound=0,upperBound=1000000000,ans;
if(sum[n]<w)
{
printf("zhx is naive!\n");
continue;
}
while(lowerBound<=upperBound)
{
int mid=(lowerBound+upperBound)>>1;
if(DFS(n+1,mid,0))
{
upperBound=mid-1;
ans=mid;
}
else lowerBound=mid+1;
}
printf("%d\n",ans);
}
return 0;
}