1. 程式人生 > ><牛客練習賽20>

<牛客練習賽20>

最短 sca pre view while else lse include return

A.禮物

題意:有n種1元禮物和m種2元禮物 你有k元你能搭配出多少種組合

題解:他們都寫的背包 發現我不會

   就枚舉買幾個1元的禮物 剩下部分買2元的 然後用組合數學搞搞

技術分享圖片
#include <stdio.h>
#include <algorithm>
#include <iostream>
using namespace std;
typedef long long ll;

ll f[2005][2005];
void fun(ll mod)
{
    for(int i = 0; i <= 2000; i++) f[i][0] = 1LL;
    for
(int i = 1; i <= 2000; i++) { for(int j = 1; j <= i; j++) f[i][j] = (f[i - 1][j - 1] + f[i - 1][j]) % mod; } } int main() { int T; scanf("%d", &T); while(T--) { ll n, m, k, p; cin>>n>>m>>k>>p; fun(p); ll ans
= f[k + n - 1][k]; if(m != 0) { for(int i = 1; i < k; i++) { if((k - i) & 1) continue; int j = (k - i) >> 1; ans = (ans + f[i + n - 1][i] * f[j + m - 1][j] % p) % p; } } if
(k % 2 == 0) ans = (ans + f[k / 2 + m - 1][k / 2]) % p; printf("%lld\n", ans); } return 0; }
View Code

B.麻婆豆腐

題意:給出n枚硬幣正面朝上的概率 求有多少子集使得硬幣正面朝上次數為奇數的概率等於偶數

題解:發現對於一個集合 如果有正面朝上概率為0.5的硬幣 那麽其余硬幣隨便怎麽搞都滿足

   比如我們要求正面朝上的概率為奇數的個數 假設除了0.5的硬幣其他硬幣為奇數的概率為p 為偶數的概率為1-p

   那麽p為奇數 = p*0.5 + (1 - p)*0.5 所以含有0.5正面朝上概率硬幣的子集一定滿足

技術分享圖片
#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <cmath>
using namespace std;
typedef long long ll;

int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        int cnt = 0;
        int n; cin>>n;
        double x;
        for(int i = 1; i <= n; i++)
        {
            cin>>x;
            if(fabs(x - 0.5) < 1e-7) cnt++;
        }
        ll ans = ((1LL << (ll)cnt) - 1LL) * (1LL << (ll)(n - cnt));
        printf("%lld\n", ans);
    }
    return 0;
}
View Code

C.尋寶

題意:n個點 每個點能到達另外一個點 選擇一個點作為起點 能最多經歷多少不同的點

題解:n個點n條邊 那麽這一定是由一些帶環樹組成的 dfs找出每一塊然後記憶化更新答案

技術分享圖片
#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
const int maxn = (1 << 24) + 5;
typedef long long ll;

vector<int> g;
int to[maxn];
int dp[maxn];
int vis[maxn];

int st;
void dfs(int x)
{
    dp[x] = 1;
    vis[x] = -1;
    int v = to[x];
    if(v == x)
    {
        vis[x] = 1;
        return;
    }

    if(vis[v] == 1) dp[x] += dp[v];
    else if(vis[v] == 0)
    {
        dfs(v);
        if(st == -1) dp[x] += dp[v];
        else if(x == st)
        {
            g.push_back(x);
            int tmp = g.size();
            for(int i = 0; i < g.size(); i++) dp[g[i]] = tmp;
            st = -1;
            g.clear();
        }
        else g.push_back(x);
    }
    else if(vis[v] == -1) st = v, g.push_back(x);
    vis[x] = 1;
}

int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        st = -1;
        ll a, b, c, n;
        cin>>a>>b>>c>>n;

        for(ll i = 0; i < n; i++)
        {
            dp[i] = 0; vis[i] = 0;
            to[i] = (a * i * i  + b * i + c) % n;
            to[i] = (to[i] + n) % n;
        }
        int ans = 0;
        for(int i = 0; i < n; i++)
        {
            if(!vis[i]) dfs(i);
            ans = max(ans, dp[i]);
        }
        printf("%d\n", ans);
    }
    return 0;
}
View Code

D.最短路2

題意:在網格圖上給兩個點和一條直線 能從網格和直線上走 求最短路

題解:以兩個點做出一個正方形 然後這條直線最多會和這個正方形有兩個交點 以這些點建圖跑最短路就好了

   直線上兩個點之間的距離是普通距離 其他則是曼哈頓距離

技術分享圖片
#include <bits/stdc++.h>
#include <stdio.h>
#include <iostream>
using namespace std;

double x1, yy, x2, y2, a, b, c;

struct node
{
    double x, y;
    int ty;
}E[25];

struct no1
{
    int to;
    double val;
};
vector<no1> g[35];

double dis[35];
int vis[25];
queue<int> que;

void spfa()
{
    for(int i = 1; i <= 10; i++) dis[i] = 1000000005;
    memset(vis, 0, sizeof(vis));
    dis[1] = 0; vis[1] = 1;
    while(!que.empty()) que.pop();
    que.push(1);

    while(!que.empty())
    {
        int u = que.front();
        que.pop();
        vis[u] = 0;
        for(int i = 0; i < g[u].size(); i++)
        {
            if(dis[u] + g[u][i].val < dis[g[u][i].to])
            {
                dis[g[u][i].to] = dis[u] + g[u][i].val;
                if(!vis[g[u][i].to])
                {
                    vis[g[u][i].to] = 1;
                    que.push(g[u][i].to);
                }
            }
        }
    }
}

int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        for(int i = 1; i <= 20; i++) g[i].clear();
        scanf("%lf %lf %lf %lf %lf %lf %lf", &x1, &yy, &x2, &y2, &a, &b, &c);
        double xx = min(x1, x2);
        double xd = max(x1, x2);
        double yx = min(yy, y2);
        double yd = max(yy, y2);
        E[1].x = x1; E[1].y = yy; E[1].ty = 0;
        E[2].x = x2; E[2].y = y2; E[2].ty = 0;
        E[3].x = x1; E[3].y = y2; E[3].ty = 0;
        E[4].x = x2; E[4].y = yy; E[4].ty = 0;
        int cnt = 4;


        if(fabs(a) > 1e-9)
        {
            double x3 = (c - b * yy) / a;
            if(x3 >= xx && x3 <= xd)
            {
                cnt++;
                E[cnt].x = x3; E[cnt].y = yy; E[cnt].ty = 1;
            }

            double x4 = (c - b * y2) / a;
            if(x4 >= xx && x4 <= xd)
            {
                cnt++;
                E[cnt].x = x4; E[cnt].y = y2; E[cnt].ty = 1;
            }
        }

        if(fabs(b) > 1e-9)
        {
            double y3 = (c - a * x1) / b;
            if(y3 >= yx && y3 <= yd)
            {
                cnt++;
                E[cnt].x = x1; E[cnt].y = y3; E[cnt].ty = 1;
            }

            double y4 = (c - a * x2) / b;
            if(y4 >= yx && y4 <= yd)
            {
                cnt++;
                E[cnt].x = x2; E[cnt].y = y4; E[cnt].ty = 1;
            }
        }

        for(int i = 1; i <= cnt; i++)
        {
            for(int j = 1; j <= cnt; j++)
            {
                if(i == j) continue;
                if(E[i].ty + E[j].ty < 2)
                {
                    no1 p; p.to = j; p.val = fabs(E[i].x - E[j].x) + fabs(E[i].y - E[j].y);
                    g[i].push_back(p);
                }
                else if(E[i].ty + E[j].ty == 2)
                {
                    no1 p; p.to = j; p.val = sqrt((E[i].x - E[j].x) * (E[i].x - E[j].x) + (E[i].y - E[j].y) * (E[i].y - E[j].y));
                    g[i].push_back(p);
                }
            }
        }
        spfa();
        printf("%.3lf\n", dis[2]);
    }
    return 0;
}
View Code

E.托米歷險記 簽到

技術分享圖片
#include <stdio.h>
#include <algorithm>
#include <iostream>
using namespace std;
int sum[5];

int main()
{
    bool f = true;
    int n;
    scanf("%d", &n);
    for(int i = 1; i <= n; i++)
    {
        int x; scanf("%d", &x);
        x /= 25;
        if(x == 1) sum[1]++;
        else if(x == 2)
        {
            if(!sum[1]) f = false;
            sum[1]--;
            sum[2]++;
        }
        else if(x == 4)
        {
            if(sum[1] && sum[2])
            {
                sum[1]--;
                sum[2]--;
            }
            else if(!sum[2])
            {
                sum[1] -= 3;
                if(sum[1] < 0) f = false;
            }
            else if(!sum[1]) f = false;
        }
    }
    if(f) puts("YES");
    else puts("NO");

    return 0;
}
View Code

F.填數字 隨便貪心

技術分享圖片
#include <stdio.h>
#include <algorithm>
#include <iostream>
using namespace std;
int a[15];

int main()
{
    int n; cin>>n;

    int zd = 10000000; int mark = -1;
    for(int i = 1; i <= 9; i++)
    {
        cin>>a[i];
        if(a[i] <= zd)
        {
            zd = a[i];
            mark = i;
        }
    }
    zd = n / a[mark];

    if(zd == 0) puts("-1");
    else
    {
        int x = zd * a[mark];
        int res = n - x;
        int cnt = 0;

        for(int i = 9; i > mark; i--)
        {
            while(res >= a[i] - a[mark])
            {
                res -= a[i] - a[mark];
                cnt++;
                printf("%d", i);
            }
        }
        for(int i = cnt + 1; i <= zd; i++) printf("%d", mark);
        puts("");
    }
    return 0;
}
View Code

<牛客練習賽20>