NOIP模拟6

期望得分: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
",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
");
            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);
    } 
} 
View Code

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);
    
}
View Code

暴力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);
    
}
View Code

暴力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);
}
View Code

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);
}
View Code
原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/7507578.html