2018牛客国庆集训派对 day3

D:很水的签到题。

#include<bits/stdc++.h>
using namespace std;
int n,m;
double a[1050];
int b[1050];
bool cmp(int x,int y)
{
    return x>y;
}
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        cin>>n>>m;
        int cnt=0;
        for(int i=0; i<n; i++)
        {
            cin>>a[i]>>b[i];
            if(b[i])
                cnt++;
        }
        sort(a,a+n,cmp);
        double ans=0;
        cnt=min(cnt,m);
        for(int i=0;i<cnt;i++)
        {
            ans+=a[i]/2;
        }
        for(int i=cnt;i<n;i++)
            ans+=a[i];
        printf("%.1f\n",ans);
    }
}

H:题意不是很清楚,但是发现和树的结构没有关系,只要考虑如何把树上的结点分成几部分就可以了,推完发现是个组合数取模,我们预处理阶乘,用乘法逆元即可。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
const int mod=1e9+7;
ll fac[maxn];
void init_fac()
{
    fac[0]=fac[1]=1;
    for(int i=2;i<maxn;i++)
       fac[i]=i*fac[i-1]%mod;
}
 
ll quickpow(ll a,ll n)
{
    ll ret=1;
    while(n)
    {
        if(n&1) ret=ret*a%mod;
        a=a*a%mod;
        n>>=1;
    }
    return ret;
}
ll C(ll a,ll b)
{
    return fac[a]*quickpow(fac[b],mod-2)%mod*quickpow(fac[a-b],mod-2)%mod;
}
 
int main()
{
    int t;
    scanf("%d",&t);
    init_fac();
    while(t--)
    {
        int n,m;
        scanf("%d %d",&n,&m);
        for(int i=1;i<n;i++)
        {
            int x,y;
            scanf("%d %d",&x,&y);
        }
        ll ans=C(n-1,m-1)*fac[m]%mod;
        printf("%lld\n",ans);
    }
}

A:问马走日最少几步,原题,可以考虑把终点放在第一象限角平分线的上方,通过找规律可以得出答案。

#include<bits/stdc++.h>
using namespace std;

int main()
{
    int x, y, ans;
    int t;
    cin>>t;
    while(t--)
    {
        cin>>x>>y;
        x=abs(x);
        y=abs(y);
        if(x>y)swap(x, y);

        if(y==x*2)
        {
            printf("%d\n", (x+y)/3);
            continue;
        }
        if(y<=2*x)
        {
            if(x==1&&y==1)
                ans = 2;
            else if(x==2&&y==2)
                ans = 4;
            else
                ans = (x+y)/3+(x+y)%3;
        }
        else
        {
            ans=x;
            int c=(y-2*x)%4;
            ans+=c;
            ans+=(y-2*x-c)/2;
            if(y==1&&x==0)
                ans=3;
        }
        printf("%d\n",ans);
    }
    return 0;
}

I:判断是否二分图

有奇环一定不是二分图,否则一定是二分图。

最开始我考虑bfs染色,但是发现无法打印环,于是我记录了成环的2个结点又用了一次dfs搜路径,然后爆内存了。

所以要打印路径,直接写dfs即可,但是记住加一个记号判断是否形成奇环,有奇环层层递归退出程序,否则dfs还会一直搜下去,程序会T。

#include<bits/stdc++.h>
using namespace std;
int const maxn=3e5+5;
vector<int>G[maxn];
int color[maxn];
int pre[maxn];
bool iscircle;
bool dfs(int v,int c)
{
    color[v]=c;
    for(int i=0; i<G[v].size(); i++)
    {
        if(color[v]==color[G[v][i]])
        {
            iscircle=true;
            int cnt=0;
            int tem=v;
            int tmp=G[v][i];
            while(v!=tmp)
            {
                cnt++;
                v=pre[v];

            }
            printf("%d\n",cnt+1);
            while(tem!=tmp)
            {
                printf("%d ",tem);
                tem=pre[tem];
            }
            printf("%d ",tem);
            return false;
        }
        if(color[G[v][i]]==0)
        {
            pre[G[v][i]]=v;
            dfs(G[v][i],-c);
            if(iscircle) return false; //这里要下个标记不然会T
        }
    }
    return true;

}
int main()
{
    int n,m;
    scanf("%d %d",&n,&m);
    for(int i=1; i<=m; i++)
    {
        int u,v;
        scanf("%d %d",&u,&v);
        G[u].push_back(v);
        G[v].push_back(u);
    }
    memset(color,0,sizeof(color));
    iscircle=false;
    if(dfs(1,1))
    {
        printf("0\n");
        for(int i=1; i<=n; i++)
        {
            if(color[i]==1)
                printf("1 ");
            else printf("0 ");
        }
    }
}

未完待续......

猜你喜欢

转载自blog.csdn.net/zero___zero/article/details/82936156