B.牛牛的DRB迷宫II
题解
看到构造题就傻眼了,当时脑子一直在想组合数的方法.....
事后问了学长,由于这是一个方案叠加,所以我们通过拆二进制的方法来解决这个问题
1 1 1 1
1 1 1 2
1 1 2 4
1 2 4 8
这个就是我们构造的2的幂的解。那么剩下的呢,举个例子吧,比如是11
1 1 1 1 1
1 1 1 2 3
1 1 2 4 3
1 2 4 8 11
因为语言难以描述,所以我就不描述了
学长说构造题拆二进制是常见思路,那我就先记下吧
#include<bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
typedef long long LL;
typedef pair<int,int> PII;
#define X first
#define Y second
inline int read()
{
int x=0,f=1;char c=getchar();
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=x*10+c-'0';c=getchar();}
return x*f;
}
int x,len=1,dp[50][50],i,j,k;
char a[52][52];
int main()
{
x=read();
if(!x)x=1000000007;
for(i=31;i>=0;i--)if(x>>i)break;
printf("%d %d\n",i+1,i+2);
for(j=0;j<i+1;j++)for(k=0;k<i+2;k++)a[j][k]='B';
for(k=0;k<i+2;k++)a[i][k]='R';
for(j=1;j<i;j++)for(k=0;k<i-j;k++)a[j][k]='D';
for(j=0;j<=i;j++)a[j][i+1]='D';
for(j=0;j<i;j++)if(x>>j&1)a[j][i]='B';else a[j][i]='D';
for(j=0;j<i+1;j++)printf("%s\n",a[j]);
return 0;
}
E.牛牛的随机数
题解
根据套路肯定是算每个二进制位对答案的贡献,那么我们只需要求一个函数\(f(x,i)\) 表示在\([1,x]\) 区间内二进制位\(i\) 出现了多少次1,然后将贡献叠加即可。
(这个所谓的函数虽然就几行,但是好难写)
J.牛牛的宝可梦Go
题解
我开始想了一个\(O(m*n^2)\) 的做法,是设\(dp[i][j]\) 表示当前在\(i\) 时间,在\(j\) 城市的最大值,但是转移是\(O(n)\) 的,所以不行
换一个思路\(DP\) 设\(dp[i]\) 表示当前捕捉了神奇宝贝\(i\) 的最大价值,转移的话就从最近200个开始转移,因为200个以外的,都距离超过200个时间了,必能走到、
细节1:图可能不联通(这个意识到了)
细节2:\(dp\) 数组应该先设为\(-oo\) ,要不然有可能从不合法的地方继承过来(死于此)
#include<bits/stdc++.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
typedef long long LL;
typedef pair<int,int> PII;
#define X first
#define Y second
inline int read()
{
int x=0,f=1;char c=getchar();
while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=x*10+c-'0';c=getchar();}
return x*f;
}
const int maxn=210,maxm=100010;
int n,m,u,v,w,tot,dis[maxn][maxn];
LL dp[maxm],ans;//dp[i][j]表示当前在i城市,j时间的最大值
struct Pokemon
{
int t,p,val;
Pokemon() {}
Pokemon(int _1,int _2,int _3):t(_1),p(_2),val(_3) {}
bool operator < (const Pokemon &s)const {return t<s.t;}
}a[maxm];
int main()
{
mem(dis,42);
n=read();m=read();
while(m--)u=read(),v=read(),dis[u][v]=dis[v][u]=1;
for(int i=1;i<=n;i++)dis[i][i]=0;
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
m=read();
for(int i=1;i<=m;i++)
{
u=read(),v=read(),w=read();
if(dis[1][v]>500)continue;
a[++tot]=Pokemon(u,v,w);
}
m=tot;
sort(a+1,a+m+1);
a[0].p=1;
for(int i=1;i<=m;i++)dp[i]=-1ll<<60;
for(int i=1;i<=m;i++)
for(int j=i-1;j>=max(0,i-500);j--)
if(dis[a[i].p][a[j].p]<=a[i].t-a[j].t)dp[i]=max(dp[i],dp[j]+a[i].val);
for(int i=0;i<=m;i++)ans=max(ans,dp[i]);
printf("%lld\n",ans);
return 0;
}
废话
细节杀我