寒假集训欢乐赛1
C题 选数
一开始想写dfs,可是。。可是一直TLE wwwww
后来看了orz代码,思路是:
先暴力 a [i]+a [j],再用二分找 a [mid],代码:
#include<bits/stdc++.h>
using namespace std;
const int N=5e3+5;
int n,m;
int a[N];
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
cin>>a[i];
sort(a+1,a+1+n);
int ans=0;
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
int l=j+1,r=n;
if(l>n)
break;
while(l<=r)
{
int mid=(l+r)>>1;
if(a[i]+a[j]+a[mid]>m)
r=mid-1;
else
{
l=mid+1;
ans=max(ans,a[i]+a[j]+a[mid]);
}
}
}
}
cout<<ans;
return 0;
}
D题 跳一跳
这题。一开始也是写的dfs |_|
果不其然TLE
其实,i从n点开始往前遍历,从i点向后跳,跳到哪个点就将能到达的点的b数组对应的值加入i点对应的值,表示多了b[i+k*a[i]]种情况,因为一开始是从1出发,所以最后输出b[1]即可
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=5e3+5;
int a[N];
int b[N];
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
for(int i=1;i<=n;i++)
b[i]=1;
for(int i=n;i>=1;i--)
{
int k=1;
while(i+k*a[i]<=n)
{
b[i]+=b[i+k*a[i]];
b[i]%=998244353;
k++;
}
}
cout<<b[1]%998244353;
}
E题 怎么这么多bug!?
当时没有时间看。。以为很难的,结果是个dp,dp[j][k]表示某个学生打了j行代码,出现了k个bug所有的情况种类。那么显然dp[0][0]=1;接下来就是状态转移,第一层遍历学生(会有n个学生,需要将dp增大),第二层遍历代码行数,第三层遍历会出现的bug数,最后ans将每个学生有可能写bug的情况都加起来
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=505;
int n,m,b,p;
int a[N];
int dp[N][N];
int main()
{
int ans=0;
cin>>n>>m>>b>>p;
for(int i=1;i<=n;i++)
cin>>a[i];
dp[0][0]=1;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
for(int k=a[i];k<=b;k++)
dp[j][k]=(dp[j][k]+dp[j-1][k-a[i]])%p;
for(int i=0;i<=b;i++)
ans=(ans+dp[m][i])%p;
cout<<ans<<endl;
}
寒假集训天梯赛1
C题 宝藏
是个dp没错了,好像背包,但是条件好像多了一点,
一开始是这么想的没错,可是后来。。写了一个状态转移方程,可是一直不对,于是就走上歪路子了。。。
后来发现,其实是少了一个判定,对重物重量的遍历应该在外层,因为(i-1,j)和(i,j-1)不一定存在最大重量值,所以应该让k在不同值都遍历一次,这样就能解决最优方案的子方案不相邻的问题了
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=505;
int n,m,b,p;
int a[N];
int dp[N][N];
int main()
{
int ans=0;
cin>>n>>m>>b>>p;
for(int i=1;i<=n;i++)
cin>>a[i];
dp[0][0]=1;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
for(int k=a[i];k<=b;k++)
dp[j][k]=(dp[j][k]+dp[j-1][k-a[i]])%p;
for(int i=0;i<=b;i++)
ans=(ans+dp[m][i])%p;
cout<<ans<<endl;
}
其他题目前还没头绪。。嘿嘿,未完待续......