codeforces round #428 div2

A:暴力模拟,能加就加,如果累计到了8就加上,每次累积

#include<bits/stdc++.h>
using namespace std;
int main()
{
    int n,k ,cnt = 0;
    scanf("%d%d", &n, &k);
    for(int i = 1; i <= n; ++i)
    {
        int x;
        scanf("%d", &x);
        cnt += x;
        if(cnt >= 8) 
        {
            k -= 8;
            cnt -= 8;
        }
        else
        {
            k -= cnt;
            cnt = 0;
        }
        if(k <= 0)
        {
            printf("%d\n", i);
            return 0;
        }
    }
    puts("-1");
    return 0;
}
View Code

B:模拟,情况有点多,先每四个人分配位置,四人座不够分配二人座,然后每两个人分配,两人坐没了分配四人座,分配四人座的时候每次统计+1,如果两人四人都没了两个四人座剩下的可以给两个人坐在边上,剩下一个人就把两人坐四人座分配,两人座可以做一个人,四人座可以做两个人,之前统计+1可以坐一个人

#include<bits/stdc++.h>
using namespace std;
const int N = 100010;
int n, k;
int a[N];
int main()
{
    scanf("%d%d", &n, &k);
    int cnt1 = n * 2, cnt2 = n, one = 0; 
    for(int i = 1; i <= k; ++i) 
    {
        scanf("%d", &a[i]);
        int x = a[i] / 4;
        a[i] %= 4;
        if(cnt2 >= x) cnt2 -= x;
        else
        {
            x -= cnt2;
            cnt2 = 0;
            if(cnt1 >= 2 * x) cnt1 -= 2 * x;
            else
            {
                puts("NO");
                return 0;
            }
        }
    }    
    for(int i = 1; i <= k; ++i)
    {
        if(a[i] == 0) continue;
        int x = a[i] / 2;
        a[i] %= 2;
        if(cnt1 >= x) cnt1 -= x;
        else
        {
            x -= cnt1;
            cnt1 = 0;
            if(cnt2 >= x) 
            {
                cnt2 -= x;
                one += x;
            }
            else if(one >= x * 2)
            {
                one -= x * 2;
            }
            else
            {
                puts("NO");
                return 0;
            }
        }
    }
    one += 2 * cnt2 + cnt1; 
    for(int i = 1; i <= k; ++i)
    {
        if(a[i] == 0) continue;
        --one;
        if(one < 0)
        {
            puts("NO");
            return 0;
        }
    }
    puts("YES");
    return 0;
}
View Code

C:一个比较简单的概率dp,每次dp[v]=dp[u]/(size[u]-(last == 0)),如果是根节点last=0没有前继,概率就是度数,否则度数-1,然后叶子结点的概率乘上步长就是答案

#include<bits/stdc++.h>
using namespace std;
const int N = 100010;
int n;
double ans;
double dp[N];
vector<int> G[N];
void dfs(int u, int last, int dis)
{
    if(G[u].size() == 1) ans += dp[u] * (double)dis; 
    for(int i = 0; i < G[u].size(); ++i)
    {
        int v = G[u][i];
        if(v == last) continue;
        dp[v] = dp[u] * 1.0 / (double)(G[u].size() - (last != 0));
        dfs(v, u, dis + 1);
    }
}
int main()
{
    scanf("%d", &n);
    dp[1] = 1.0;
    for(int i = 1; i < n; ++i)
    {
        int u, v;
        scanf("%d%d", &u, &v);
        G[u].push_back(v);
        G[v].push_back(u);
    }
    dfs(1, 0, 0);
//    for(int i = 1; i <= n; ++i) printf("dp[%d]=%.6f\n", i, dp[i]);
    printf("%.8f\n", ans);
    return 0;
}
View Code

D:一个很好的题,我们用容斥原理来做,设cnt[i]表示能整除i的a[i]的个数,ans[i]表示gcd为i的子序列的答案,我们发现直接计算ans似乎有些困难,但是我们可以容斥,我们放宽条件,先找出gcd能整除i的子序列的人的总和的可能的总数,是C(n,1)*1+C(n,2)*2+C(n,3)*3+...+C(n,n)*n,意思是n个人选1个人的方案数*1个人,n个人选两个人*两个人,统计了所有子序列的总人数,然后我们加一项C(n,0)*0,然后倒序相加,就得到了n*(C(n,0)+C(n,1)+...+C(n,n))/2=n*2^n/2=n*2^n-1,这是gcd是n的倍数的答案,然后根据容斥原理,我们把ans[i*2],ans[i*3]...减去,剩下的就是答案

这其实跟莫比乌斯反演挺像的,就是限制太强就用容斥弱化一下

#include<bits/stdc++.h>
using namespace std;
const int N = 200010, mod = 1000000007; 
int n;
int a[N], has[N * 10], cnt[N * 10];
long long ans[N * 10];
long long answer;
inline int read()
{
    int x = 0, f = 1; char c = getchar();
    while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); }
    while(c >= '0' && c <= '9') { x = x * 10 + c - '0'; c = getchar(); }
    return x * f;
}
long long power(long long x, long long t)
{
    long long ret = 1;
    for(; t; t >>= 1, x = x * x % mod) if(t & 1) ret = ret * x % mod;
    return ret;
}
int main()
{
    scanf("%d", &n);
    for(int i = 1; i <= n; ++i) 
    {
        a[i] = read();
        ++has[a[i]];
    }
    for(int i = 2; i <= 1000000; ++i)
        for(int j = i; j <= 1000000; j += i) cnt[i] += has[j];
    for(int i = 1000000; i >= 2; --i) if(cnt[i] > 0)
    {
        ans[i] = (long long)cnt[i] * (long long)power(2, cnt[i] - 1) % mod;
        for(int j = i * 2; j <= 1000000; j += i) ans[i] -= ans[j];
        answer = (answer + (long long)i * ans[i]) % mod;
    }
    printf("%lld\n", (answer % mod + mod) % mod);
    return 0;
}
View Code

 

posted @ 2017-08-14 22:41  19992147  阅读(150)  评论(0编辑  收藏  举报