码迷,mamicode.com
首页 > 其他好文 > 详细

Codeforces Round #257 (Div. 2)

时间:2014-07-25 19:03:12      阅读:332      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   color   使用   os   io   for   

A.Jzzhu and Children

  计算每个人会出现的轮次数,取最后一个且轮次数最大的,注意是用a[i]-1 % m,倒着扫一遍就行了

 

#include <iostream>
#include <cstdio>
#include <cstdlib>

using namespace std;

const int maxn = 100+10;

int n, m;
int a[maxn];

int main()
{
#ifdef LOCAL
    freopen("450A.in", "r", stdin);
#endif
    cin >> n >> m;
    int last_one = n, divide = 0;
    for(int i = 1; i <= n; i++) 
        cin >> a[i];
    for(int i = n; i >= 1; i--)
        if((a[i]-1) / m > divide) {
            divide = (a[i]-1)/m;
            last_one = i;
        }
    cout << last_one << endl;
    return 0;
}

 

B.Jzzhu and Sequences

  很容易推出f[i] = f[i-1]+f[i+1],推出每个六个数一个循环,只需要预处理出f[1]~f[6]就行了

  需要注意的是f[i]可能小于-P,需要(f[i]+2*p)%p,以前写过一种保险的取模,小于0的情况,计算其负数是x倍p,加上(x+1)*P再取模

  例如-5, 2  5/2=2  (-5+3*2)%2 = 1

  

#include <iostream>
#include <cstdio>
#include <cstdlib>

using namespace std;

const long long p = 1000000007;

long long n, sign, ans;
long long f[3];

int main()
{
#ifdef LOCAL
    freopen("450B.in", "r", stdin);
#endif
    cin >> f[0] >> f[1];
    f[2] = f[1] - f[0];
    cin >> n;
    if(((n-1)/3)&1) sign = -1;
    else    sign = 1;
    ans = sign*f[(n-1)%3];
    if(ans > 0) ans %= p;
    else    ans = (ans+2*p)%p;
    cout << ans << endl;
    return 0;
}

 

C.Jzzhu and Chocolate

  很烦人的题,首先能够得出最后答案是floor(m/x)*floor(n/y),这个卡了我很久...

  一种方法是直接通过数学分析这个式子

  我是自己乱yy:主要考虑是整除情况:如果m%x0==0那么这个解比起其他x是更优的,

  于是我就分情况写得很细,看代码吧。。。就是如果一边能整除,先让其满足

 

#include <iostream>
#include <cstdio>
#include <cstdlib>

using namespace std;

long long n, m, k, ans;

int main()
{
#ifdef LOCAL
    freopen("450C.in", "r", stdin);
#endif
    cin >> n >> m >> k;
    if(n+m-2 < k)   cout << -1 << endl;
    else {
        if(n % (k+1) == 0)
            ans = n/(k+1)*m;
        else if(m % (k+1) == 0)
            ans = m/(k+1)*n;
        else if(n - 1 >= k && m - 1 >= k)
            ans = max(n/(k+1)*m, m/(k+1)*n);
        else if(n - 1 >= k)
            ans = n/(k+1)*m;
        else if(m - 1 >= k)
            ans = m/(k+1)*n;
        else {
            long long rn = k-(n-1), rm = k-(m-1);
            if(m % (rn+1) == 0) 
                ans = m/(rn+1);
            else if(n % (rm+1) == 0)
                ans = n/(rm+1);
            else 
                ans = max(m/(rn+1), n/(rm+1));
        }
        cout << ans << endl;
    }
    return 0;
}

 

D.Jzzhu and Cities

  一开始学长讲的 先求一次最短路(不包括铁路) 然后去扫一遍看 哪些铁路能够删去...因为反例很容易举出就是 当两个相连的城市都需要铁路才能到达centre时,是可能只需要一条铁路的,这种方法会跑两条.错在得出的推论是在考虑1-a的铁路时,是不需要考虑a相邻节点的最短路的,因为他们的最短路更新时是w[a,v]+dis[a]...说不清了!这个推论成立的前提是1-a是通路...

  然后我考虑标记每个点是否使用铁路

  在dijkstra做最短路的时候,我们每次都会选边去更新,我把后面铁路也当作普通边加入,不过做上标记,这样在更新最短路的时候,维护每个点是否经由铁路到达1,注意是要所选的铁路最少:

  如果该点已经使用铁路且使用道路距离<=当前距离  update

  如果该点距离<当前距离  update

 

  其实就是要多考虑用道路替换铁路情况(尽管dis不变),不过我的代码写得不是很清晰,包含了更多的情况,只是由于每个城市最多取一条铁路,不影响答案

  最后扫一遍记录使用铁路的结点数, ans = k-cnt

 

  PS:边比较多...听说裸spfa会挂,所以还是dijkstra+heap好写呢

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <queue>
#include <cstring>

using namespace std;

const int maxn = 1000000+50;
const long long inf = ~0llu >> 1;

struct Edge{
    int u, v;
    long long  w;
    void init(int u, int v, long long  w) {
        this->u = u;    this->v = v;
        this->w = w;
    }
}edge[maxn*4];

typedef pair<long long, int> pii;

int n, m, k, edgecnt;
int head[maxn], next[maxn];
long long dis[maxn];
bool istrain[maxn], used[maxn];

void addEdge(int u, int v, long long w)
{
    edge[edgecnt].init(u, v, w);
    next[edgecnt] = head[u];
    head[u] = edgecnt++;
}

void dijkstra()
{
    bool done[maxn];
    priority_queue<pii, vector<pii>, greater<pii> > q;
    memset(done, 0, sizeof(done));
    for(int i = 1; i <= n; i++)
        dis[i] = inf;
    dis[1] = 0;
    q.push(make_pair(0, 1));
    while(!q.empty()) {
        pii tmp = q.top();  q.pop();
        int u = tmp.second;
        if(done[u]) continue;
        done[u] = true;
        for(int e = head[u]; e != -1; e = next[e]) {
            int v = edge[e].v;
            if((used[v] && dis[v] == dis[u]+edge[e].w) || dis[v] > dis[u]+edge[e].w) {
                dis[v] = dis[u]+edge[e].w;
                used[v] = istrain[e];
                q.push(make_pair(dis[v], v));
            }
        }
    }
}

int main()
{
#ifdef LOCAL
    freopen("450D.in", "r", stdin);
#endif
    memset(head, -1, sizeof(head));
    memset(next, -1, sizeof(next));
    memset(istrain, 0, sizeof(istrain));
    memset(used, 0, sizeof(used));
    scanf("%d%d%d", &n, &m, &k);
    for(int i = 0; i < m; i++) {
        int u, v;
        long long w;
        scanf("%d%d%lld", &u, &v, &w);
        addEdge(u, v, w);
        addEdge(v, u, w);
    }
//  for(int i = 1; i <= n; i++)
//      cout << dis[i] << endl;
    for(int i = 0; i < k; i++)  {
        int v;
        long long w;
        scanf("%d%lld", &v, &w);
        istrain[edgecnt] = true;
        addEdge(1, v, w);
    }    
    dijkstra();
    int cnt = 0;
    for(int i = 2; i <= n; i++)
        cnt += used[i];
    printf("%d\n", k-cnt);
    return 0;
}

 

  当场只写了ABC,其中A挂了一发,B因为没考虑f[i]+2p的情况,WA,C题虽然搞出来了...不过耗时近1h

  最后rating很不错,300+,rank+260!!!!!!!!就突然从1200+ ->1500

  D题只看了会,有大概思路,但是最短路都不熟0 0  

 

//写完这个的时候实际上下一场都已经做完了。。。

Codeforces Round #257 (Div. 2),布布扣,bubuko.com

Codeforces Round #257 (Div. 2)

标签:style   blog   http   color   使用   os   io   for   

原文地址:http://www.cnblogs.com/gemmeg/p/3867996.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!