Codeforces #304 div2 only

2015-06-27 17:02:20

传送门

总结:去上海前的一场比赛,当时没有打,今天来补交作业.... 

  题目难度不大,赛中AK。

  A、B水,C题没有说明正负... 被坑了2发,后来打了暴力过掉,D、E思路都不难,但是需要 coding 时间。

 

A题:模拟

B题:排序

 

C题:模拟

  题意 & 思路:大意是两人玩纸牌游戏,问谁赢,或产生无限循环,直接模拟百万次即可。

#include <cstdio>
#include <ctime>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;

#define getmid(l,r) ((l) + ((r) - (l)) / 2)
#define MP(a,b) make_pair(a,b)
#define PB(a) push_back(a)

typedef long long ll;
typedef pair<int,int> pii;
const double eps = 1e-8;
const int INF = (1 << 30) - 1;

int n,k1,k2;
queue<int> q1,q2;

int main(){
    scanf("%d",&n);
    scanf("%d",&k1);
    int a;
    for(int i = 1; i <= k1; ++i){
        scanf("%d",&a);
        q1.push(a);
    }
    scanf("%d",&k2);
    for(int i = 1; i <= k2; ++i){
        scanf("%d",&a);
        q2.push(a);
    }
    int o = 3000000;
    while(--o){
        if(q1.empty() || q2.empty()) break;
        int v1 = q1.front(); q1.pop();
        int v2 = q2.front(); q2.pop();
        if(v1 > v2){
            q1.push(v2);
            q1.push(v1);
        }
        else{
            q2.push(v1);
            q2.push(v2);
        }
    }
    if(o == 0){
        printf("-1\n");
        return 0;
    }
    printf("%d ",3000000 - o - 1);
    if(q1.empty()) printf("2\n");
    else printf("1\n");
    return 0;
}
View Code

 

 

D题:欧拉筛,前缀和

  题意:给出 n = a!/ b!,(1<= b <= a <= 5000000),每轮让 n 整除其一个因子 x ,变成 n / x,问最多进行几轮。

  思路:显然每次除掉 n 的一个素因子。那么就是计算 n 素因子分解后每个素因子指数的和(简称素因子个数和)。

  可以用欧拉筛预处理出每个数的素因子个数和,然后处理出其前缀和 sum[] 来表示阶乘的素因子个数和,那么答案就是 sum[a] - sum[b]。

#include <cstdio>
#include <ctime>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;

#define getmid(l,r) ((l) + ((r) - (l)) / 2)
#define MP(a,b) make_pair(a,b)
#define PB(a) push_back(a)

typedef long long ll;
typedef pair<int,int> pii;
const double eps = 1e-8;
const int INF = (1 << 30) - 1;
const int MAXN = 5000000;

int t;
int cnt[MAXN + 10];
ll sum[MAXN + 10];
int check[MAXN + 10];
int prime[1000000];
int tot;

void Pre(){
    for(int i = 2; i <= MAXN; ++i){
        if(!check[i]) prime[++tot] = i,cnt[i] = 1;
        for(int j = 1; j <= tot && i * prime[j] <= MAXN; ++j){
            cnt[i * prime[j]] = cnt[i] + 1;
            check[i * prime[j]] = 1;
            if(i % prime[j] == 0) break;
        }
    }
    for(int i = 1; i <= MAXN; ++i)
        sum[i] = sum[i - 1] + cnt[i];
}

int main(){
    Pre();
    int a,b;
    scanf("%d",&t);
    for(int o = 1; o <= t; ++o){
        scanf("%d%d",&a,&b);
        printf("%I64d\n",sum[a] - sum[b]);
    }
    return 0;
}
View Code

 

 

E题:最大流

  题意:给出 n 个点,m 条边的无向图。(n <= 100 , m <= 200),第 i 个点开始有 ai 个士兵,每个士兵可以选择留守在原来的点,也可以走向相邻的点(只能走一步),然后给出 b1~bn,问能否达到第 i 个点有 bi 个士兵的状态。如果可以,则输出一个转移矩阵,m[i][j] 表示第 i 个点转移给第 j 个点 m[i][j] 个士兵。

  思路:因为要输出解,所以网络流是比较好的选择。

  将 1~n 号点拆点,入点为 1~n,出点 n+1 ~ 2×n,源点为0,汇点为2×n+1,源点向每个入点的边的容量为 ai,出点向汇点的边的容量为 bi 。对于 m 条输出的边,比如边 (a,b),给 a 的入点和 b 的出点建边,同时给 b 的入点和 a 的出点建边,容量为无穷。跑一遍最大流后判断总流量是否为 sum(bi),如果是,扫一遍残余网络的所有边就可以统计出转移矩阵了。

  注意:坑点在于,如果 sum(ai) != sum(bi),必然不可行。

#include <cstdio>
#include <ctime>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;

#define getmid(l,r) ((l) + ((r) - (l)) / 2)
#define MP(a,b) make_pair(a,b)
#define PB(a) push_back(a)
#define MEM(a,b) memset(a,b,sizeof(a))

typedef long long ll;
typedef pair<int,int> pii;
const double eps = 1e-8;
const int INF = (1 << 30) - 1;
const int MAXN = 410;
const int MAXM = 10000;

int n,m;
int A[MAXN],B[MAXN];
int ans[MAXN][MAXN];

struct edge{
    int u,v,next,c,f;
};

struct Max_flow{
    int st,ed,lev[MAXN],first[MAXN],now[MAXN],ecnt;
    edge e[MAXM];
    void init(int a,int b){
        st = a,ed = b;
        MEM(first,-1);
        ecnt = 0;
    }
    void add_edge(int u,int v,int c,int f){
        e[ecnt].next = first[u];
        e[ecnt].u = u;
        e[ecnt].v = v;
        e[ecnt].c = c;
        e[ecnt].f = f;
        first[u] = ecnt++;

        e[ecnt].next = first[v];
        e[ecnt].u = v;
        e[ecnt].v = u;
        e[ecnt].c = 0;
        e[ecnt].f = 0;
        first[v] = ecnt++;
    }
    bool bfs(){
        queue<int> Q;
        while(!Q.empty()) Q.pop();
        Q.push(st);
        MEM(lev,-1);
        lev[st] = 0;
        while(!Q.empty()){
            int x = Q.front(); Q.pop();
            for(int i = first[x]; ~i; i = e[i].next){
                int v = e[i].v;
                if(lev[v] < 0 && e[i].c > 0){
                    lev[v] = lev[x] + 1;
                    Q.push(v);
                }
            }
        }
        return lev[ed] != -1;
    }
    int dfs(int p,int minf){
        if(p == ed || minf == 0) return minf;
        for(int &i = now[p]; ~i; i = e[i].next){
            int v = e[i].v;
            if(lev[v] == lev[p] + 1 && e[i].c > 0){
                int d = dfs(v,min(e[i].c,minf));
                if(d > 0){
                    e[i].c -= d;
                    e[i ^ 1].c += d;
                    return d;
                }
            }
        }
        return 0;
    }
    int dinic(){
        int max_flow = 0,pl;
        while(bfs()){
            memcpy(now,first,sizeof(first));
            while((pl = dfs(st,INF)) > 0)
                max_flow += pl;
        }
        return max_flow;
    }
}MF;

int main(){
    scanf("%d%d",&n,&m);
    MF.init(0,2 * n + 1);
    int sum = 0,sum1 = 0;
    for(int i = 1; i <= n; ++i) scanf("%d",A + i),sum1 += A[i];
    for(int i = 1; i <= n; ++i) scanf("%d",B + i),sum += B[i];
    int a,b;
    for(int i = 1; i <= m; ++i){
        scanf("%d%d",&a,&b);
        MF.add_edge(a,n + b,INF,1);
        MF.add_edge(b,n + a,INF,1);
    }
    for(int i = 1; i <= n; ++i){
        MF.add_edge(i,i + n,INF,1);
        MF.add_edge(0,i,A[i],0);
        MF.add_edge(i + n,2 * n + 1,B[i],0);
    }
    int max_flow = MF.dinic();
    if(sum1 != sum || max_flow != sum){
        printf("NO\n");
        return 0;
    }
    for(int i = 0; i < MF.ecnt; ++i) if(MF.e[i].f){
        int u = MF.e[i].u;
        int v = MF.e[i].v - n;
        ans[u][v] = INF - MF.e[i].c;
    }
    printf("YES\n");
    for(int i = 1; i <= n; ++i){
        printf("%d",ans[i][1]);
        for(int j = 2; j <= n; ++j) printf(" %d",ans[i][j]);
        puts("");
    }
    return 0;
}
View Code

 

posted @ 2015-06-27 17:37  Naturain  阅读(154)  评论(0编辑  收藏  举报