杭电多校(四)2019.7.31--暑假集训

【HDU 6014】

SOLVED

【题目大意】给定N个节点,两点之间距离是节点编号的与,在这样的前提下,求最小生成树,输出代价和路径

【思路】通过lowbit求第一个0的位置,然后令此位为1的值就是最优解

【总结】1.与或非都要先考虑拆分后二进制的特性

2.检验算法正确性时,验证数据要是自己验证能力的最大值

(就是多验)

#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 = 2e5 + 10;
int arr[maxn];
int lowbit(int x)
{
    return x & -x;
}
int main()
{
    ios_base::sync_with_stdio(false);
    int T;
    cin >> T;
    while (T--)
    {
        int N;
        cin >> N;
        int cal = 0;
        for (int i = 2; i <= N; i++)
        {
            if ((i & 1) == 0)
                arr[i] = 1;
            else
            {
                int t =lowbit((i + lowbit(i)));
                if (t <= N)
                    arr[i] = t;
                else
                {
                    arr[i] = 1;
                    cal++;
                }
            }
        }
        cout << cal << "\n";
        for (int i = 2; i <= N; i++)
        {
            cout << arr[i];
            if (i != N)
                cout << ‘ ‘;
        }
        cout << "\n";
    }
}



【HDU 6015】

UNSOLVED



【HDU 6016】

UNSOLVED



【HDU 6017】

UNSOLVED



【HDU 6018】

UNSOLVED



【HDU 6019】

UNSOLVED



【HDU 6020】

SOLVED

【题目大意】给一个4*4的数字谜题,能否恢复到指定形状

【思路】数字谜题的结论

#include<iostream>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#include<string>
#include<cstring>
#include<climits>
#include<cmath>
#include<map>
#include<set>
#include<deque>
#include<unordered_map>
using namespace std;
struct node
{
    int arr[5][5];
    bool operator<(const node& a)const
    {
        for (int i = 1; i <= 4; i++)
        {
            for (int j = 1; j <= 4; j++)
            {
                if (arr[i][j] >= a.arr[i][j])
                    return false;
            }
        }
        return true;
    }
    node() {};
    node(const int a[][5])
    {
        for (int i = 1; i <= 5; i++)
        {
            for (int j = 1; j <= 5; j++)
            {
                arr[i][j] = a[i][j];
            }
        }
    }
};
map<node, int>mp;
int arr[16];
const int mx[4] = { 0,-1,0,1 };
const int my[4] = { 1,0,-1,0 };
int main()
{
    ios_base::sync_with_stdio(false);
    int T;
    cin >> T;
    while (T--)
    {
        int cal = 0;
        int px;
        for (int i = 1; i <= 16; i++)
        {
            int n;
            cin >> n;
            if (n == 0)
            {
                px = (i - 1) / 4 + 1;
                continue;
            }
            arr[++cal] = n;
        }
        int cnt = 0;
        for (int i = 1; i <= 15; i++)
        {
            for (int j = i + 1; j <= 15; j++)
            {
                if (arr[i] > arr[j])
                    cnt++;
            }
        }
        if ((cnt + 4 - px) % 2 == 0)
            cout << "Yes\n";
        else
            cout << "No\n";
    }
}



【HDU 6021】

UNSOLVED



【HDU 6022】

UNSOLVED



【HDU 6023】

SOLVED

【题目大意】

【思路】对素数进行特殊处理,先求N^1/5,于是剩下的素数的幂次最高只能是4了,可以二分开根迅速求解

#include<cstdio>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
ll pri[10001];
int vis[10001];
int cntp;
void init()
{
    for (ll i = 2; i < 10000; i++)
    {
        if (!vis[i])
        {
            cntp++;
            pri[cntp] = i;
        }
        for (int j = 1; j <= cntp&&pri[j]*i<10000; j++)
        {
            vis[i*pri[j]] = 1;
            if (i%pri[j] == 0)
            {
                break;
            }

        }
    }
}
ll sqrt(ll num,int d)
{
    ll l = 1, r = num;
    while (l <= r)
    {
        ll mid = (l+r) / 2;
        ll tmp = LLONG_MAX;
        if(d==3)
        {
            tmp = tmp / mid;
        }
        if (d == 4)
        {
            tmp = tmp / mid;
            tmp /= mid;
        }
        if (tmp / mid < mid)
        {
            r = mid - 1;
            continue;
        }
        tmp = 1;
        for (int i = 1; i <= d; i++)
            tmp *= mid;
        if (tmp == num)
            return mid;
        if (tmp > num)
            r = mid - 1;
        else
            l = mid + 1;
    }
    return 0;
}
int main()
{
    init();
    int T;
    scanf("%d", &T);
    while (T--)
    {
        ll n;
        scanf("%lld", &n);

        int ans = INT_MAX;
        for (int i = 1; i <= cntp; i++)
        {
            if (pri[i] > n)
                break;
            int cnt = 0;
            while (n%pri[i] == 0)
            {
                cnt++;
                n/= pri[i];
            }
            //if (cnt)
            //    printf("cnt %d pri %lld\n", cnt, pri[i]);
            if (cnt < ans && cnt)
                ans = cnt;
        }
        int res = INT_MAX;
        if (n>1)
        {
            if (sqrt(n, 4))
                res = min(res, 4);
            else
            {
                if (sqrt(n, 2))
                    res = min(res, 2);
            }
            if (sqrt(n, 3))
                res = min(res, 3);
            if (res == INT_MAX && n > 4500)
                res = 1;
        }
        printf("%d\n", min(ans,res));
    }    //printf("1000000000000000000 %lld  %lld\n", sqrt(1000000000000000000, 3), sqrt(1000000000000000000, 2));
    return 0;
}

原文地址:https://www.cnblogs.com/rentu/p/11297739.html

时间: 2024-10-05 20:54:15

杭电多校(四)2019.7.31--暑假集训的相关文章

HDU 4902 Nice boat 2014杭电多校训练赛第四场F题(线段树区间更新)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4902 解题报告:输入一个序列,然后有q次操作,操作有两种,第一种是把区间 (l,r) 变成x,第二种是把区间 (l,r) 中大于x的数跟 x 做gcd操作. 线段树区间更新的题目,每个节点保存一个最大和最小值,当该节点的最大值和最小值相等的时候表示这个区间所有的数字都是相同的,可以直接对这个区间进行1或2操作, 进行1操作时,当还没有到达要操作的区间但已经出现了节点的最大值跟最小值相等的情况时,说明

2019杭电多校第九场

2019杭电多校第九场 熟悉的后半场挂机节奏,又苟进首页了,很快乐 1001. Rikka with Quicksort upsolved 不是我做的,1e9调和级数分段打表 1002. Rikka with Cake solved at 01:11 有一个矩形,给你很多射线(射线只有横平竖直的四个方向),问把矩形切成了多少块 队友说答案是交点数加一,作为一个合格的工具人,当然是把队友的想法实现啦 二维坐标离散化枚举纵坐标维护横坐标,常规套路,树状数组也可以做(我是线段树写习惯了根本没想起来还有

HDU 4864 Task (贪心+STL多集(二分)+邻接表存储)(杭电多校训练赛第一场1004)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4864 解题报告:有n台机器用来完成m个任务,每个任务有一个难度值和一个需要完成的时间,每台机器有一个可以工作的最长时间和一个可以完成的任务的难度的最大值, 一台机器能完成一个任务的条件是这台机器的最长工作时间和能完成任务的难度值必须都大于等于这个任务,而且一台机器最多完成一个任务,假设一个任务的时间为t,难度值为x,那么完成这个任务可以赚到的钱 money = 500 * t + 2 * x; 现在

HDU 4941 Magical Forest(map映射+二分查找)杭电多校训练赛第七场1007

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4941 解题报告:给你一个n*m的矩阵,矩阵的一些方格中有水果,每个水果有一个能量值,现在有三种操作,第一种是行交换操作,就是把矩阵的两行进行交换,另一种是列交换操作,注意两种操作都要求行或列至少要有一个水果,第三种操作是查找,询问第A行B列的水果的能量值,如果查询的位置没有水果,则输出0. 因为n和m都很大,达到了2*10^9,但水果最多一共只有10^5个,我的做法是直接用结构体存了之后排序,然后m

HDU 4937 (杭电多校 #7 1003题)Lucky Number(瞎搞)

题目地址:HDU 4937 多校的题以后得重视起来...每道题都错好多次...很考察细节.比如这道....WA了无数次.... 这题的思路自己真心想不到...这题是将进制后的数分别是1位,2位,3位和更多位的分开来计算. 当是1位的时候,显然只有3到6,此时只能是-1 当是2位的时候,可以转换成一元一次方程求解 当是3位的时候,可以转换成一元二次方程求解 当是4位的时候,此时最多也只有7000个数,7000^3接近1e12.所以剩下的直接枚举进制数来判断即可. 代码如下: #include <i

HDU 4975 (杭电多校 #10 1005题)A simple Gaussian elimination problem.(网络流之最大流)

题目地址:HDU 4975 对这题简直无语...本来以为这题要用什么更先进的方法,结果还是老方法,这么卡时间真的好吗....比赛的时候用了判环的方法,一直TLE..后来换了矩阵DP的方式,加了加剪枝就过了..无语了.. 代码如下: #include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <cstdio> #include <

HDU 4888 (杭电多校#3)Redraw Beautiful Drawings(网络流之最大流)

题目地址:HDU 4888 自己之所以弱真心是态度的问题,以后不能再偷懒了!!那次这个题一直没补,结果这次又遇到了..还有这次遇到的最小割权闭合问题,也一直没刷,所以这次遇到了也不会,连是最小割都不知道!!(突然想起来前面还有好多题拖到现在也没做...T U T)以后绝不能再拖拉了! 这题的建图是很容易的,主要是判断唯一性不好判断.这里是用的dfs找环来判断是否唯一,因为假如有环的话,说明环 中的数字是可以相互流动而且可以保证解依然正确.. 代码如下: #include <cstdio> #i

HDU 5742 It&#39;s All In The Mind (贪心) 2016杭电多校联合第二场

题目:传送门. 题意:求题目中的公式的最大值,且满足题目中的三个条件. 题解:前两个数越大越好. #include <iostream> #include <algorithm> #include <cstdio> #include <cstring> using namespace std; int gcd(int a,int b) { if(!b) return a; return gcd(b,a%b); } int main() { int t; ci

HDU 4940(杭电多校#7 1006) Destroy Transportation system(瞎搞)

题目地址:HDU 4940 当时这个题一看就看出来了是网络流的最小割,然后就一直在想建图..然后突然发现,应该要让T集合的数目最少,不然只要有两个,那这两个的每一个都可以跑到S集合,使得T集合变小.那就只能是1个了.然后..枚举就好了..但是虽然觉得这么做肯定没错..但是不敢敲..因为当时都3个小时了才只有10个队过了...后来又想了几遍后觉得这样没错,就写完交上了.果然AC... 代码如下: #include <iostream> #include <cstdio> #inclu

HDU 4901(杭电多校训练#3 1005题)The Romantic Hero(DP)

题目地址:HDU 4901 这题没想到最后居然能够做出来.... 这题用了两次DP,先从前往后求一次异或的,再从后往前求一次与运算的.分别是 1:求异或的时候,定义二维数组huo[1000][1024],前者指第几位,后者是哈希的思想,若huo[x][y]=2则表示最右边的数为第x位时,异或值为y的出现了两次,需要再定义一个hash数组,来保存前面出现的所有情况,再找有多少位的时候,用hash数组中出现的所有的值与当前的第x位的数字进行异或. 2:求与的时候,定义二维数组yu[1000][102