杭电多校(三)2019.7.29--暑假集训

【HDU 6003】

UNSOLVED

 

 


【HDU 6004】

SOLVED

【题目大意】有一DAG图,n个节点,m次询问,每次询问两个节点,求令两个节点任意一个和叶节点失去联通的方法数

【思路】支配树,没有听说过于是被当场爆锤(知道了也是被锤的命QwQ

 

#include<iostream>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#include<string>
#include<cstring>
#include<climits>
#include<cmath>
#include<map>
#include<set>
#include<deque>
using namespace std;
const int maxn = 200010;
vector<int>G[maxn];
int indegree[maxn];
int nex[maxn][30];
int dis[maxn];
int lca_num[maxn];
int N, M;
void init(int n)
{
    for (int j = 1; (1 << j) <= N; j++)
        nex[n][j] = nex[nex[n][j - 1]][j - 1];
}
int lca(int a, int b)
{
    if (b == -1)
        return a;
    if (dis[a] < dis[b])
        swap(a, b);
    int delta_distance = dis[a] - dis[b];
    int base = 0;
    while (delta_distance)
    {
        if (delta_distance & 1)
            a = nex[a][base];
        base++;
        delta_distance >>= 1;
    }
    if (a == b)
        return a;
    for (int i = log2(N); i >= 0; i--)
    {
        if (nex[a][i] != nex[b][i])
        {
            a = nex[a][i];
            b = nex[b][i];
        }
    }
    return nex[a][0];
}
int main()
{
    ios_base::sync_with_stdio(false);
    int T;
    cin >> T;
    while (T--)
    {
        memset(lca_num, -1, sizeof(lca_num));
        memset(indegree, 0, sizeof(indegree));
        memset(dis, 0, sizeof(dis));
        memset(nex, 0, sizeof(nex));
        cin >> N >> M;
        for (int i = 0; i <= N; i++)
            G[i].clear();
        for (int i = 1; i <= M; i++)
        {
            int u, v;
            cin >> u >> v;
            G[v].push_back(u);
            indegree[u]++;
        }
        queue<int>que;
        for (int i = 1; i <= N; i++)
        {
            if (indegree[i] == 0)
            {
                lca_num[i] = 0;
                que.push(i);
            }
        }
        while (!que.empty())
        {
            int n = que.front();
            que.pop();
            nex[n][0] = lca_num[n];
            dis[n] = dis[lca_num[n]] + 1;
            init(n);
            for (int to : G[n])
            {
                lca_num[to] = lca(n, lca_num[to]);
                if (--indegree[to]==0)
                    que.push(to);
            }
        }
        int Q;
        cin >> Q;
        for (int i = 1; i <= Q; i++)
        {
            int a, b;
            cin >> a >> b;
            cout << dis[a] + dis[b] - dis[lca(a, b)] << "\n";
        }
    }
}
View Code

【HDU 6005】

UNSOLVED

 

 


【HDU 6006】

UNSOLVED

 

 


【HDU 6007】

UNSOLVED

 


【HDU 6008】

SOLVED

【思路】循环节

 

 

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include <iostream>
#include <algorithm>
using namespace std;
using ll = long long int;
ll T, x, n, ans;
ll a[]={2, 3, 5, 7, 11, 13, 17, 19};

ll pow_mul(ll a, ll b, ll r)
{
    ll ans = 0;
    while(b)
    {
        if(b & 1)
        ans = (ans + a) % r;
        a = (a + a) % r;
        b >>= 1;
    }
    return ans % r;
}

ll pow_mod(ll a, ll b, ll r)
{
    ll ans = 1;
    while(b)
    {
        if(b & 1) 
        ans = pow_mul(ans, a, r) % r;
        a = pow_mul(a, a, r) % r;
        b >>= 1;
    }
    return ans % r;
}

bool test(ll a, ll p, ll d)
{
    
    if(p % 2 == 0) return false;
    while(!(d & 1)) d >>= 1;
    ll t = pow_mod(a, d, p); //得到 a^d % p 
    while(d != p - 1)
    {
        ll y = pow_mul(t, t, p); // t^2 % p
        if(y == 1)
        
        {
            if(t != 1 && t != p - 1) 
              return false;//不满足二次探测定理 
            return true; //满足的话后面的肯定也满足了 因为此时y = 1 
        } 
        t = y; d <<= 1;
    }
    return t == 1; //最后一次测试 a^(p - 1) % p = 1 
}

bool isprime(ll x)
{
    for(int i = 0; i < 8; i ++)
    {
        if(a[i] == x) return true;
        if(!test(a[i], x, x - 1))
           return false;
    } 
    return true;       
}ll mul(ll a,ll b,ll mod)
  {
      ll ret = 0;
      while (b)
        {
            if (b & 1)
              ret = (a + ret) % mod;
        b >>= 1;
        a = (a + a) % mod; 
        }
    return ret;
   } 
ll quicmod(ll a,ll b,ll mod)
  {
      ll ret = 1;
      while (b)
        {
            if (b & 1)
              {
                  ret = mul(ret,a,mod);
              }
        b >>= 1;
        a = mul(a,a,mod);
        }
    return ret;
   } 
int main()
{
    int T;
    scanf("%d",&T);
    while (T--)
      {
          ll p,Q,ret = 0;
          scanf("%lld",&Q);
          p = Q - 1;
          ret = Q - 1;

          while (isprime(p) == 0)
            ret = mul(ret,quicmod(p,Q - 2,Q),Q),p--;
        printf("%lld\n",ret);
      }
    return 0;
}
View Code

【HDU 6009】

SOLVED

【题目大意】一个数列,令1<=i<=n,每个wi都有都要满足到此前缀和小于m,如果大于则需要从前i-1个数中删除,直到符合条件,输出每位最少需要删除的数字个数

【思路】有点类似主席树,建一颗值域线段树,每次遍历动态更新节点,然后保存和,然后二分向下查找

 

#include<iostream>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#include<string>
#include<cstring>
#include<climits>
#include<cmath>
#include<map>
#include<set>
#include<deque>
using namespace std;
const int maxn = 200010;
typedef pair<int, int>P;
P arr[maxn];
int rnk[maxn];
struct segment_tree
{
    struct node
    {
        int left, right, mid;
        long long sum, num;
    };
    node tree[4 * maxn];
    void update(int k)
    {
        tree[k].sum = tree[k << 1].sum + tree[k << 1 | 1].sum;
        tree[k].num = tree[k << 1].num + tree[k << 1 | 1].num;
    }
    void build_tree(int l, int r, int k = 1)
    {
        tree[k].left = l;
        tree[k].right = r;
        tree[k].mid = (r + l) >> 1;
        if (l == r)
            return;
        const int& m = tree[k].mid;
        build_tree(l, m, k << 1);
        build_tree(m + 1, r, k << 1 | 1);
    }
    void change_interval(int l, int r, int k = 1)
    {
        if (l <= tree[k].left && tree[k].right <= r)
        {
            tree[k].sum += arr[tree[k].left].first;
            tree[k].num++;
            return;
        }
        const int& m = tree[k].mid;
        if (l <= m)
            change_interval(l, r, k << 1);
        if (r > m)
            change_interval(l, r, k << 1 | 1);
        update(k);
    }
    int query(long long x, int k = 1)
    {
        if (tree[k].sum <= x)
            return 0;
        int ans = 0;
        if (tree[k].left == tree[k].right)
            return 1;
        if (tree[k << 1].sum <= x)
            ans += query(x - tree[k << 1].sum, k << 1 | 1);
        else
        {
            ans += tree[k << 1 | 1].num;
            ans += query(x, k << 1);
        }
        return ans;
    }
}my_tree;
int main()
{
    ios_base::sync_with_stdio(false);
    int T;
    cin >> T;
    while (T--)
    {
        memset(&my_tree, 0, sizeof(my_tree));
        int N, K;
        cin >> N >> K;
        for (int i = 1; i <= N; i++)
        {
            cin >> arr[i].first;
            arr[i].second = i;
        }
        sort(arr + 1, arr + N + 1);
        for (int i = 1; i <= N; i++)
        {
            rnk[arr[i].second] = i;
        }
        my_tree.build_tree(1, N);
        for (int i = 1; i <= N; i++)
        {
            cout << my_tree.query(K - arr[rnk[i]].first) << " ";
            my_tree.change_interval(rnk[i], rnk[i]);
        }
        cout << "\n";
    }
}
View Code

【HDU 6010】

UNSOLVED

 

 


【HDU 6011】

UNSOLVED

 

 


【HDU 6012】

UNSOLVED

 

 


【HDU 6013】

UNSOLVED

 

posted @ 2019-08-04 10:58  rentu  阅读(187)  评论(0编辑  收藏  举报