期望得分:100+100+100=300
实际得分:0+100+90=190
T1 superman
二分给每条边加多少,判断是否存在负环
#include<queue> #include<cstdio> #include<cstring> #include<algorithm> #define N 501 #define M 4951 using namespace std; int n,tot,front[N],to[M],nxt[M],val[M],val_[M]; int front_[N],to_[M],nxt_[M]; int cnt[N],dis[N]; bool vis[N],ok[N]; void add(int u,int v,int w) { to[++tot]=v; nxt[tot]=front[u]; front[u]=tot; val_[tot]=w; to_[tot]=u; nxt_[tot]=front_[v]; front_[v]=tot; } bool spfa() { memset(cnt,0,sizeof(cnt)); memset(dis,63,sizeof(dis)); memset(vis,false,sizeof(vis)); queue<int>q; vis[1]=true; q.push(1); dis[1]=0; cnt[1]++; int now; while(!q.empty()) { now=q.front(); q.pop(); vis[now]=false; for(int i=front[now];i;i=nxt[i]) { if(!ok[to[i]]) continue; if(dis[to[i]]>dis[now]+val[i]) { dis[to[i]]=dis[now]+val[i]; if(!vis[to[i]]) { vis[to[i]]=true; q.push(to[i]); cnt[to[i]]++; if(cnt[to[i]]>n) return false; } } } } return dis[n]>=0; } bool check(int mid) { for(int i=1;i<=tot;i++) val[i]=val_[i]+mid; return spfa(); } void solve(int tmp) { for(int i=1;i<=tot;i++) val[i]=val_[i]+tmp; spfa(); printf("%d\n",dis[n]); } void dfs(int x) { ok[x]=true; for(int i=front[x];i;i=nxt[i]) if(!ok[to[i]]) dfs(to[i]); } void dfs2(int x) { ok[x]=true; for(int i=front_[x];i;i=nxt_[i]) if(!ok[to_[i]]) dfs2(to_[i]); } int main() { freopen("superman.in","r",stdin); freopen("superman.out","w",stdout); int T,m,u,v,w; scanf("%d",&T); while(T--) { tot=0; memset(front,0,sizeof(front)); memset(front_,0,sizeof(front_)); scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { scanf("%d%d%d",&u,&v,&w); add(u,v,w); } memset(ok,false,sizeof(ok)); dfs(1); if(!ok[n]) { printf("-1\n"); continue; } memset(ok,false,sizeof(ok)); dfs2(n); int l=-100000,r=100000,mid,tmp; while(l<=r) { mid=(l+r)/2; if(check(mid)) tmp=mid,r=mid-1; else l=mid+1; } solve(tmp); } }
T2 洛谷 P2647 最大收益
https://www.luogu.org/problem/show?pid=2647
如果一共选m个,第i个选了第j个物品,那对答案的贡献为wj-(m-i)*rj
所以如果确定选哪m个,肯定是先选rj小的
去除m的影响,倒着枚举
AC代码
#include<cstdio> #include<algorithm> #define N 3001 using namespace std; struct node { int w,r; }e[N]; int wi[N],ri[N],dp[N][N]; bool cmp(node p,node q) { return p.r>q.r; } int main() { //freopen("market.in","r",stdin); //freopen("market.out","w",stdout); int n,ans=0; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d%d",&e[i].w,&e[i].r); sort(e+1,e+n+1,cmp); for(int i=1;i<=n;i++) for(int j=1;j<=i;j++) dp[i][j]=max(dp[i-1][j],dp[i-1][j-1]+e[i].w-e[i].r*(j-1)); for(int i=1;i<=n;i++) ans=max(ans,dp[n][i]); printf("%d",ans); }
暴力1
#include<cstdio> #include<algorithm> #define N 3001 using namespace std; struct node { int w,r; }e[N]; int wi[N],ri[N],dp[N][N]; bool cmp(node p,node q) { return p.r<q.r; } int main() { int n,ans=0; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d%d",&e[i].w,&e[i].r); sort(e+1,e+n+1,cmp); for(int k=1;k<=n;k++) { for(int i=1;i<=n;i++) for(int j=1;j<=min(i,k);j++) dp[i][j]=max(dp[i-1][j],dp[i-1][j-1]+e[i].w-(k-j)*e[i].r); ans=max(ans,dp[n][k]); } printf("%d",ans); }
暴力2
#include<cstdio> #include<algorithm> #define N 3001 using namespace std; struct node { int w,r; }e[N]; int wi[N],ri[N]; bool cmp(node p,node q) { return p.r<q.r; } int main() { int n; scanf("%d",&n); for(int i=0;i<n;i++) scanf("%d%d",&wi[i],&ri[i]); int S=1<<n,tot=0,tmp,ans=0; for(int i=1;i<S;i++) { tot=0; for(int j=0;j<n;j++) if(i&(1<<j)) e[++tot].w=wi[j],e[tot].r=ri[j]; sort(e+1,e+tot+1,cmp); tmp=0; for(int j=1;j<=tot;j++) tmp+=e[j].w-(tot-j)*e[j].r; ans=max(ans,tmp); } printf("%d",ans); }
T3 洛谷 P2759 奇怪的函数
x>=logx 10^(n-1)
x>=[log10 10^(n-1)]/log 10 x
x>=(n-1)/log10 x
特判当x=1时,答案为1
#include<cstdio> #include<cmath> using namespace std; typedef long long LL; int n; int main() { //freopen("Lemon_Soda.in","r",stdin); //freopen("Lemon_Soda.out","w",stdout); scanf("%d",&n); LL l=1,r=1ll<<62,mid,ans; if(n==1) { printf("1"); return 0; } while(l<=r) { mid=l+r>>1; if((n-1)*1.0/log10(mid)<=mid) r=mid-1,ans=mid; else l=mid+1; } printf("%lld",ans); }