Codeforces Round #407 (Div. 2)

来自FallDream的博客,未经允许,请勿转载,谢谢。

------------------------------------------------------

A.Anastasia and pebbles

你有两个口袋,每种口袋最多只能装k个物品,有n种物品,每种物品有ai个,两种不同的物品不能混在一起,问最少要装多少次.

题解:.............

#include<iostream>
#include<cstdio>
#include<cmath>
#include<queue>
#include<cstring>
#include<queue>
#include<algorithm>
#include<map>
#define ll long long
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}

ll n,k;
ll ans=0;

int main()
{
    n=read();k=read();
    for(int i=1;i<=n;i++)
    {
        ll x=read();
        ans+=(x+k-1)/k;
    }
    cout<<(ans+1)/2;
    return 0;
}

B.Masha and geometric depression
给定一个等比数列,第一项是b1,之后每一项是前一项乘以q,但是b1和q都可以是负数或0。你还有m个不吉利的数字。每当满足abs(b)<=l的时候,你会把b写出来,除非它是一个不吉利的数字。

问你会写出多少个数字,当然你可能写出无限多的数字。

题解:大判断。  一开始我以为不满足还能继续写....结果pretest WA了一排...

#include<iostream>
#include<cstdio>
#include<cmath>
#include<queue>
#include<cstring>
#include<queue>
#include<algorithm>
#include<map>
#define ll long long
using namespace std;
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}

int b1,q,l,m;
map<int,bool> mp;

inline int abs(int x){return x<0?-x:x;}

int main()
{
    b1=read();q=read();l=read();m=read();
    if(abs(b1)>l) return 0*puts("0");
    for(int i=1;i<=m;i++)mp[read()]=1;
    if(b1==0)
    {
        if(mp[0])return 0*puts("0");
        else return 0*puts("inf");
    }
    if(q==0)
    {
        if(!mp[0])return 0*puts("inf");
        if(abs(b1)<=l&&!mp[b1]) return 0*puts("1");
        puts("0");
        return 0;
    }
    if(q==1)
    {
        if(abs(b1)<=l&&!mp[b1])return 0*puts("inf");
        else return 0*puts("0");
    }
    if(q==-1)
    {
        int ans=0;
        if(abs(b1)<=l&&!mp[b1])ans++;
        if(abs(b1)<=l&&!mp[-b1]) ans++;
        if(ans) return 0*puts("inf");
        else return 0*puts("0");
    }
    else
    {
        int ans=(abs(b1)>l||mp[b1])?0:1;
        while(1LL*abs(q)*abs(b1)<=(ll)l)
        {
            b1*=q;
            if(abs(b1)<=l&&!mp[b1])ans++;
        }
        cout<<ans<<endl;
    }
    return 0;
}

C.Functions again

给定一个数字序列ai和函数f,求f的最大值。  $n\leqslant 100000$

 题解:发现每一种$|a[i]-a[i+1]|$只有两种不同的贡献,分开计算即可。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<queue>
#include<cstring>
#include<queue>
#include<algorithm>
#define ll long long
#define INF 1000000000
#define MN 100000000
using namespace std;
inline ll read()
{
    ll x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}

int n;
int a[100005];
ll f[100005],f2[100005];
ll ans=0;
int abs(int x){return x<0?-x:x;}

int main()
{
    n=read();
    for(int i=1;i<=n;i++)a[i]=read();
    for(int i=1;i<=n;i++) f[i]=f[i-1]+1LL*(i&1?1:-1)*abs(a[i]-a[i+1]);
    for(int i=1;i<=n;i++) f2[i]=f2[i-1]+1LL*(i&1?-1:1)*abs(a[i]-a[i+1]);
    ll minn=0;
    for(int i=1;i<n;i++)
    {
        ans=max(ans,f[i]-minn);
        if(i%2==0)minn=min(minn,f[i]);
    }
    minn=f2[1];
    for(int i=2;i<n;i++)
    {
      //  cout<<i<<" "<<f2[i]<<" "<<ans<<" "<<minn<<endl;
        ans=max(ans,f2[i]-minn);
        if(i&1)minn=min(minn,f2[i]);
    }
    cout<<ans<<endl;
    return 0;
}

D. Weird journey

给定一个无向图,可能有自环,无重边,你要求出满足恰好有两条边只走了一次,其它都走了两次的路径数量。两种方案不同当且仅当边不同。  $n,m\leqslant 10^{6}$

题解:先判联通。然后我们把自环和普通边分开考虑。

如果都选普通边,那么这两条边一定要有公共点,用度数计算一下即可。

如果一个选自环,那么显然任意普通边都能成为另一条边。

如果两个都选自环,那么显然没问题。

#include<iostream>
#include<cstdio>
#define ll long long
#define MN 1000000
using namespace std;
inline int read()
{
    int x = 0 , f = 1; char ch = getchar();
    while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
    while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
    return x * f;
}

int n,m,cnt=0,head[MN+5],num=0,num2=0,s[MN+5];
struct edge{int to,next;}e[MN*2+5];
ll ans=0;
bool mark[MN+5],b[MN+5];
void ins (int f,int t){e[++cnt]=(edge){t,head[f]};head[f]=cnt;}

void dfs(int x)
{
    mark[x]=1;
    for(int i=head[x];i;i=e[i].next)
        if(!mark[e[i].to])
            dfs(e[i].to);
}

int main()
{
    n=read();m=read();
    for(int i=1;i<=m;i++) 
    {
        int u=read(),v=read();
        if(u==v) num2++,b[u]=1;
        else ins(u,v),ins(v,u),num++,s[u]++,s[v]++;
    }
    for(int i=1;i<=n;i++) 
        if(b[i]||head[i]) 
        {
            dfs(i);break;
        }
    for(int i=1;i<=n;i++) if(!mark[i]&&(head[i]||b[i])) return 0*puts("0");
    for(int i=1;i<=n;i++) ans+=1LL*s[i]*(s[i]-1)/2;
    ans+=1LL*num2*(m-num2)+1LL*num2*(num2-1)/2;
    printf("%lld",ans);
    return 0;
}

E. The Great Mixing

给定n个数ai,你要从中选出最少的数,每个数可以选任意次,使得平均值等于k   $n\leqslant 10^{6} , ai,k\leqslant 1000$

题解:显然n最多只有1000种,然后我们分成正的和负的考虑。我们发现我们选的数的总和不会超过$10^{6}$,所以直接bfs就可以了,复杂度不是满的,应该能比较快找出答案。

数据挺水的,直接dp好像也能过。

#include<iostream>
#include<cstdio>
#define MAXN 1000000 
using namespace std;
inline int read()
{
    int x = 0 , f = 1; char ch = getchar();
    while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
    while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
    return x * f;
}

int n,k;
bool mark[2005];
int s[1005],q[MAXN+5],top=1,cnt=0,d[MAXN+5];

int main()
{
    k=read();n=read();
    for(int i=1;i<=n;i++)
    {
        int x=read()-k+1000;
        if(!mark[x]) mark[x]=1,s[++cnt]=x-1000;
    }
    d[0]=1;
    for(int i=1;i<=top;i++)
        for(int j=1;j<=cnt;j++)
        {
            if(s[j]+q[i]==0) return 0*printf("%d",d[q[i]]);
            if(s[j]+q[i]<=MAXN&&s[j]+q[i]>=0&&!d[s[j]+q[i]]) d[s[j]+q[i]]=d[q[i]]+1,q[++top]=s[j]+q[i];
        }
    puts("-1");
    return 0;
}

 

posted @ 2017-03-30 08:46  FallDream  阅读(296)  评论(0编辑  收藏  举报