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;
}

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;
}

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;
}

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;
}

时间: 2024-10-12 10:18:11

codeforces round #428 div2的相关文章

Codeforces Round #428 (Div. 2)

Codeforces Round #428 (Div. 2) A    看懂题目意思就知道做了 #include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a; i<=b; ++i) #define per(i,b,a) for (int i=b; i>=a; --i

codeforces round #257 div2 C、D

本来应该认真做这场的,思路都是正确的. C题,是先该横切完或竖切完,无法满足刀数要求,再考虑横切+竖切(竖切+横切), 因为横切+竖切(或竖切+横切)会对切割的东西产生交叉份数,从而最小的部分不会尽可能的大. 代码如下,虽然比较长.比较乱,但完全可以压缩到几行,因为几乎是4小块重复的代码,自己也懒得压缩 注意一点,比如要判断最小块的时候,比如9行要分成2份,最小的剩下那份不是9取模2,而应该是4 m/(k+1)<=m-m/(k+1)*k          #include<bits/stdc+

codeforces Round #250 (div2)

a题,就不说了吧 b题,直接从大到小排序1-limit的所有数的lowbit,再从大到小贪心组成sum就行了 1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #define N 200000 6 using namespace std; 7 int pos[N],a[N],s[N],f[N],la[N],b[N],i,j,k,ans,n,p

Codeforces Round#320 Div2 解题报告

Codeforces Round#320 Div2 先做个标题党,骗骗访问量,结束后再来写咯. codeforces 579A Raising Bacteria codeforces 579B Finding Team Member codeforces 579C A Problem about Polyline codeforces 579D "Or" Game codeforces 579E Weakness and Poorness codeforces 579F LCS Aga

Codeforces Round #254(div2)A

很有趣的题.想到了就非常简单,想不到就麻烦了. 其实就是一种逆向思维:最后结果肯定是这样子: WBWBWBWB... BWBWBWBW... WBWBWBWB... ... 里面有“-”的地方改成“-”就行了. 但是我开始是正着想的,想每个点怎么处理,这还要看它周围点的状态,越想越麻烦... 这题中体现的正难则反的逆向思维很值得学习. #include<iostream> #include<cstdio> #include<cstdlib> #include<cs

Codeforces Round #254(div2)B

就是看无向图有几个连通块,答案就是2n-num. 范围很小,就用矩阵来存图减少代码量. #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<map> #include<set> #include<vector> #include<algorithm> #inc

Codeforces Round #260(div2)C(递推)

有明显的递推关系: f[i]表示i为数列中最大值时所求结果.num[i]表示数i在数列中出现了几次. 对于数i,要么删i,要么删i-1,只有这两种情况,且子问题还是一样的思路.那么很显然递推一下就行了:f[i]=max(f[i-1],f[i-2]+i*num[i]); 这里技巧在于:为了防止麻烦,干脆就所有数的出现次数都记录一下,然后直接从2推到100000(类似于下标排序),就不用排序了,也不用模拟删除操作了.这一技巧貌似简单,但实际上临场想出来也需要点水平. #include<iostrea

Codeforces Round #289 Div2 E

Problem 给一串长度为N的字符串,对于每个字符,若字符为元音,则权值为1,否则为0.一个子串的权值定义为该串所有字符权值之和除以字符个数,一个母串的权值定义为所有子串的权值之和.求母串的权值. Limits Time Limit(ms): 1000 Memory Limit(MB): 256 N: [1, 5*10^5] 字符集: 'A'-'Z' 元音: I E A O U Y Solution 考虑每个元音字符对母串的贡献,可以找出规律. More 举"ABCDOEFGHKMN"

Codeforces Round #403 div2 C. Andryusha and Colored Balloons

题目链接:Codeforces Round #403 div2 C. Andryusha and Colored Balloons 题意: 给你一棵n个节点的树,然后让你染色,规定相连的三个 节点不能同色,问需要的最少颜色,并输出其中一种方案. 题解: 因为只有相邻3个节点不同色. 所以直接DFS,每个节点都从1开始. 然后ans[v]!=ans[u]!=ans[fa]就行. 1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=a;i&