今日任务

第一个 写了两个比较简单的数论题目,就是整除理论的两个题目,第一个题目比较蠢,第二个稍微要动一点脑筋

Codeforces Round #347 (Div. 2) – A. Complicated GCD

Codeforces Round #146 (Div. 1) – A. LCM Challenge

这两个都说明了两个小结论:

1、相邻两个整数互质。2、相邻两个奇数互质。 

 

第二个就补了校赛的热身赛,那个lh的简单图论,

这个比较复杂,因为这个题目,我又学了一个新的lca的板子,我觉得这个新板子还不错

 

第三个就是补中南的题目

补了一个青蛙的题目,那个居然是01背包,完全没有看出来,补完题后,感觉对01背包又有了新的认识啊。

 

 

 

lh的简单图论

http://10.64.70.166/problem/1112

lh的简单图论
 

Description

 

众所周知,集训队的lh同学txdy,有一天他在写着代码,突然哼起了raprap,哟,哟哟,你看这个碗它又大又圆,就像这个题它又短又难,skrskr,skrskr。

lhlh在着手解决一个图论的问题:

已知有一个nn个点的无向图,图中有mm条边,每条边的权值为w_iwi

lhlh想知道,他从点aa走到点bb,所走的最长的边长最小值是多少?

 

Input

 

第一行输入三个正整数n,m,qn,m,q,分别表示有nn个点mm条边和qq次询问。

接下来mm行,每行有三个数分别为u_iuiv_iviw_iwi表示从点uu到点vv有一条路径边长为ww。

接下来qq行,每行有两个数aa,bb,表示lhlh想知道他从aa走到bb所走的最长的边长的最小值。

 

Output

 

输出qq行,每行一个正整数,表示他从点aa走到点bb,所走的最长的边长最小值是多少。

 

Sample Input 1 

6 6 8 
1 2 5 
2 3 4 
3 4 3 
1 4 8 
2 5 7 
4 6 2 
1 2 
1 3 
1 4 
2 3 
2 4 
5 1 
6 2 
6 1 

Sample Output 1

5 
5 
5 
4 
4 
7 
4 
5 

Hint

1n15000

1M30000

1wi1000000000

1q20000

 

 

这个题目就是比较典型的图转树,这个好像就是UVA的11354

你要用最小生成树把图转变成树,然后再用LCA处理这棵树

 

#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <string>
#include <cmath>
#include <algorithm>
#include <queue>
#include <iostream>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn = 3e4 + 100;
int dp[maxn][30];
ll gw[maxn][30];
int deep[maxn];
int n, m, q, N;
struct node
{
    int from,to;
    ll dist;
    node(int from=0,int to=0,ll dist=0):from(from),to(to),dist(dist){}
}exa[maxn];
vector<node>vec[maxn];
int f[maxn];
int findx(int x)
{
    return f[x] == x ? x : f[x] = findx(f[x]);
}

void unite(int x,int y)
{
    x = findx(x);
    y = findx(y);
    if (x == y) return;
    f[x] = y;
}

bool same(int x,int y)
{
    return findx(x) == findx(y);
}
bool cmp(node a,node b)
{
    return a.dist < b.dist;
}

void dfs(int s)
{
    for(int i=1;i<=N;i++)
    {
        dp[s][i] = dp[dp[s][i - 1]][i - 1];
        gw[s][i] = max(gw[s][i - 1], gw[dp[s][i - 1]][i - 1]);
    }
    int len = vec[s].size();
    for(int i=0;i<len;i++)
    {
        node e = vec[s][i];
        if(e.to!=dp[s][0])
        {
            deep[e.to] = deep[s] + 1;
            dp[e.to][0] = s;
            gw[e.to][0] = e.dist;
            dfs(e.to);
        }
    }
}

ll LCA(int x,int y)
{
    if (x == y) return 0;
    if (deep[x] > deep[y]) swap(x, y);
    ll ans = 0;
    for(int i=N;i>=0;i--)//抬到同一高度
    {
        if(deep[x]<deep[y]&&deep[dp[y][i]]>=deep[x])
        {
            ans = max(ans, gw[y][i]);
            y = dp[y][i];
        }
    }
    for(int i=N;i>=0;i--)//一起往上走
    {
        if(dp[x][i]!=dp[y][i])
        {
            ans = max(ans, gw[x][i]);
            ans = max(ans, gw[y][i]);
            x = dp[x][i];
            y = dp[y][i];
        }
    }
    if(x!=y)//最后一步
    {
        ans = max(ans, gw[x][0]);
        ans = max(ans, gw[y][0]);
    }
    return ans;
}

int main()
{
    cin >> n >> m >> q;
    for(int i=1;i<=m;i++)
    {
        int a, b;
        ll w;
        cin >> a >> b >> w;
        exa[i] = node(a, b, w);
    }
    for (int i = 1; i <= n; i++) f[i] = i;
    sort(exa + 1, exa + 1 + m, cmp);
    for(int i=1;i<=m;i++)
    {
        int x = exa[i].from, y = exa[i].to;
        if (same(x, y)) continue;
        unite(x,y);
        vec[x].push_back(node(x, y, exa[i].dist));
        vec[y].push_back(node(y, x, exa[i].dist));
    }
    N = (log(n + 0.0)) / log(2.0);
    deep[1] = 0;
    dfs(1);
    for(int i=1;i<=q;i++)
    {
        int x, y;
        cin >> x >> y;
        ll ans = LCA(x, y);
        cout << ans << endl;
    }
    return 0;
}

 

 

 

2249: Altruistic Amphibians

Description

A set of frogs have accidentally fallen to the bottom of a large pit. Their only means of escaping the pit is to jump out of it. Each frog i​ is described by three parameters (li, wi, hi)​ where li​ is its leap capacity, wi​ its weight, and hi​ its height. The leap capacity specifies how high that frog can jump. If a frog's leap capacity is strictly larger than the depth of the pit, the frog can directly escape the pit. However, these frogs are altruistic. Rather than selfishly saving themselves and leaving the frogs with too limited leap capacity behind, they collectively aim to save as many of them from the pit as possible.

The frogs realize that if a frog A​ climbs up on the back of frog B​ before it jumps, the first frog A​ stands a better chance of escaping the pit: it can escape if hB + lA​ is strictly larger than the depth of the pit.

Furthermore, if frog B carrying frog A on its back climbs up on the back of frog C, the situation is even better for frog A: it can now escape the pit if hC + hB + lA is strictly larger than the depth of the pit.

The frogs can build even higher piles of frogs this way, the only restriction is that no frog may carry other frogs of weight in total amounting to its own weight or heavier. Once a pile has been used to allow a frog to escape, the frogs in the pile jump back to the bottom of the pit and they can then form a new pile (possibly consisting of a different set of frogs). The question is simply how many frogs can escape the pit assuming they collaborate to maximize this number?

Input

The first line of input contains two integers n​ and d​ (1 ≤ n ≤ 100 000​, 1 ≤ d ≤ 108​), where n​ is the number of frogs and d​ is the depth of the pit in µm. Then follow n​ lines each containing three integers l, w, h​ (1 ≤ l, w, h ≤ 108​), representing a frog with leap capacity l​ µm, weight w​ µg, and height h​ µm. The sum of all frogs' weights is at most 108​ µg.

Output

Output the maximum number of frogs that can escape the pit.

Sample Input

3 19
15 5 3
12 4 4
20 10 5

Sample Output

3

Hint

Source

ncpc2018

 

这个就是一个01背包,好难看出来啊,开始我以为是贪心,昨天的一个状压dp我也以为是贪心,

所以呢,如果我觉得像贪心但是又不能肯定的,那应该是dp

代码要是看不懂,那就模拟一次就会了

 

#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <string>
#include <cmath>
#include <algorithm>
#include <queue>
#include <iostream>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int mx = 1e5 + 10;
struct node
{
    int l, w, h;
}exa[mx];

bool cmp(node a,node b)
{
    return a.w > b.w;
}
const int maxn = 1e8 + 10;
int dp[maxn];

int main()
{
    int n, d;
    cin >> n >> d;
    for(int i=0;i<n;i++)
    {
        cin >> exa[i].l >> exa[i].w >> exa[i].h;
    }
    int ans = 0;
    sort(exa , exa + n, cmp);
    for(int i=0;i<n;i++)
    {
        int w = exa[i].w;
        if (exa[i].l + dp[w] > d) ans++;
        for(int j=1;j<min(w,maxn-w);j++)
        {
            dp[j] = max(dp[j], dp[j + w] + exa[i].h);
        }
    }
    cout << ans << endl;
    return 0;
}

 

 

 

 

 

转载于:https://www.cnblogs.com/EchoZQN/p/10713097.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值