C - Average Length (atcoder.jp)
先求出每一条边用了几次,一共n!条路径,每条路径n - 1 条边,n! * (n - 1) 条边,但是任意两点之间一共有 n * (n - 1) / 2 条边 每条边用了 n! * (n - 1) / (n * (n - 1) / 2) 次;
求出边长总和 s,s * 次数 / n 即为答案。
一眼dp 但是10^6 所以考虑数学性质,只有两种形式的操作,通过解方程来求出每种操作的个数,然后排列组合。mod 是个质数 所以快速幂求逆元 加 组合数。
E - All-you-can-eat (atcoder.jp)
可以简化为 01背包,但是只要在t 时间内选了 ,就可以吃完,在二维循环时,将时间(体积)加上当前物品的时间 - 1 就可以了,这个操作的目的为了当时间只剩1 的时候 还是可以将当前物品放进去。
大佬代码
#include<bits/stdc++.h>
using namespace std;
int n,t,dp[6005],ans;
struct node{//结构体用来存储a[i]和b[i]
int a,b;
bool operator<(const node &t)const{//运算符重载
return a<t.a;
}
}a[3005];
int main()
{
scanf("%d%d",&n,&t);
for(int i=1;i<=n;i++)scanf("%d%d",&a[i].a,&a[i].b);
sort(a+1,a+n+1);//先将食物按食用时间从小到大排序
for(int i=1;i<=n;i++){
for(int j=t+a[i].a-1;j>=a[i].a;j--){//因为再t时刻之后依然可以吃菜,但必须在t时刻前点菜,所以j是从t+a[i].a-1到a[i].a的闭区间
dp[j]=max(dp[j],dp[j-a[i].a]+a[i].b);//01背包
}
}
for(int i=1;i<=5999;i++)ans=max(ans,dp[i]);//取最大值
printf("%d",ans);
return 0;
}
当k = 0 时这个问题可以很容易解决,就是积木大赛;
但是k > 0 时,需要dp;能力不足。