2018-german-collegiate-programming-contest-gcpc-18-en

Problem C: Coolest Ski Route

link

题目大意:在有向图里找一个最长路,没有入点的是起点,没有出点的是终点。用记忆化搜索

#include <bits/stdc++.h>
#define mm(a) memset(a, 0, sizeof(a));
using namespace std;

const int N = 5e3 + 7;
int n, m;
int Map[N][N];
int dp[N];
int vis[N];
int cnt[N];
void inti()
{
    mm(Map);
    mm(vis);
    mm(dp);
    mm(cnt);
}
int dfs(int op)
{
    if(vis[op]) return dp[op];
    vis[op] = 1;
    for(int i = 1; i <= n; i ++)
    {
        if(Map[op][i]) dp[op] = max(dp[op], dfs(i) + Map[op][i]);
    }
    return dp[op];
}
int main()
{
    int m;
    cin >> n >> m;
    int u, v, w;
    int i, j, k;
    inti();
    for(i = 1; i <= m; i ++)
    {
        cin >> u >> v >> w;
        cnt[v] ++;
        Map[u][v] = max(Map[u][v], w);
    }
    int Max = 0;
    for(i = 1; i <= n; i ++)
    {
        if(cnt[i] == 0)
            Max = max(Max, dfs(i));
    }
    cout << Max << endl;
    return 0;
}
/*
5 5
1 2 15
2 3 12
1 4 17
4 2 11
5 4 9
*/

Problem F: Fighting Monsters

link

思路:因为要求最后要1嘛,所以最后一个一定是1 ,0,然后再往前找,然后就非常惊奇地发现是个斐波那契数列,然后还是两列差一位的,就比如11,12,23,35,58;然后用vector数组实现,vector一维里存的是斐波那契,二维里存的是原数列中的下标。

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int N = 1e5 + 7;
const int INF = 0x3f3f3f3f;
int f[40] = {1, 1, 2, 3, 5, 8};
int a[N];
vector<int>v[40];
void inti()
{
    for(int i = 4; i <= 31; i ++)
    {
        f[i] = f[i - 1] + f[i - 2];
    }
}
int main()
{
    inti();
    int n;
    cin >> n;
    for(int i = 1; i <= n; i ++)
    {
        cin >> a[i];
        int tmp = lower_bound(f + 1, f + 32, a[i]) - f;
        if(f[tmp] == a[i])
        {
            v[tmp].push_back(i);
//            cout << f[tmp] << "*" << endl;
        }
    }
    int ansx = INF, ansy = INF;
    for(int i = 1; i <= 31; i ++)
    {
        if(v[i].size() == 0) continue;
        if(v[i + 1].size() == 0) continue;
        if(ansx > v[i][0])
        {
            ansx = v[i][0];
            ansy = v[i + 1][0];
//            cout << ansx << "&&" << ansy << endl;
        }
    }
    if(v[1].size() > 1)
    {
        if(ansx > v[1][0])
            ansx = v[1][0], ansy = v[1][1];
    }
    if(ansx != INF) cout << ansx << " " << ansy << endl;
    else cout << "impossible\n";
    return 0;
}

D - Down the Pyramid

 题意:给你一层金字塔,然后找下一层金字塔的排布会有几种情况。

思路:知道下一层的第一个是多少,后边的加加减减就都可以知道了,所以要判断后边的所有的数都不能小于等于0,然后又发现如果设第一个数为x的话,奇数列是常数 - x, 偶数列是x - 常数;然后就分奇偶讨论,找到奇偶的最大值和最小值的范围然后相减加一(因为要两头)就是答案。

#include<bits/stdc++.h>
#define mm(a) memset(a, 0, sizeof(a))
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N = 1e6 + 7;
int a[N];
int main()
{
    ios::sync_with_stdio(0);
    cin.tie();
    cout.tie();
    int n;
    cin >> n;
    int i;
    for(i = 1; i <= n; i ++)
    {
        cin >> a[i];
    }
    ll now = 0, Min = 0, Max = INF*2;
    for(i = 1; i <= n; i ++)
    {
        if(i%2)
        {
            now = a[i] - now;
            Max = min(Max, now);
        }
        else 
        {
            now = a[i] - now;
            Min = max(Min, -now);
        }
    }
    if(Max < 0 || Min < 0 || Max - Min + 1 < 0) cout << 0 << endl;
    else cout << Max - Min + 1 << endl;
    return 0;
}

E - Expired License

题意:给你俩浮点数,判断能不能用素数表示;

思路:给你x, y, 找到素数p, q,使x/y = p/q;

先让x,y乘1e5,然后除掉它们的最大公约数,再判断最后得到的数是不是素数,要注意如果最后是1 1的话,要改成2 2输出,需要特判。

答案:

#include <bits/stdc++.h>

using namespace std;

const int N = 1e5;
bool prime(int x)
{
    if(x <= 1) return false;
    int i;
    for(i = 2; i <= x/i; i ++)
    {
        if(x%i == 0) return false;
    }
    return true;
}
int gcd(int a, int b)
{
    return !b ? a : gcd(b, a%b);
}
int main()
{
    int n;
    cin >> n;
    while(n --)
    {
        double a, b;
        scanf("%lf %lf", &a, &b);
        a *= N ;
        b *= N;
       // cout << b << endl;
        int aa = (int)(a + 0.5), bb = (int)(b + 0.5);
       // cout << aa << "&" << bb << endl;
        int t = gcd(aa, bb);
        aa /= t, bb /= t;
      //  cout << t << "*" << aa << "*" << bb << endl;
        if(aa == 1 && bb == 1) cout << 2 << " " << 2 << endl;
        else 
        {
            if (prime(aa) && prime(bb))
                cout << aa << " " << bb << endl;
            else
                cout << "impossible\n";
        }
    }
    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值