2019 hdu 第四场补题 (1 ,签到题

因为太菜了,前几场的题都没补,从今天开始慢慢补

以后晚上要早睡,早上早起,抽出时间看书,每天只肝一局杀戮尖塔,上床不玩手机

每周五把一周总结的板子打印下来,毕竟老年人记性

补题顺序按难度升序

1001 AND Minimum Spanning Tree

题意:定义边的权值为两结点的&和,构造字典序最小的最小生成树

分析:

1.构造型算法

2.二进制数字默认有前导0,在纸上随便画画就发现构造将相邻点最低位0置为1,其余位为0为最优解,如果范围不够则直接置为1

题解:

1001. AND Minimum Spanning Tree

This is a very simple problem. If N is 2^k-1, the cost of MST is 1, otherwise it’s 0. Lexicographically smallest solution is also trivial. 2*k’s parent is 1, 4*k+1’s parent is 2, 8*k+3’s parent is 4, and so on. If N is 2^k-1, only N’s parent is not determined after this process. In this case, N’s parent is 1.

代码:

#include<algorithm>
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<string>
#include<map>
#include<queue>
#include<stack>
#include<list>
#include<set>
using namespace std;
typedef long long ll;
typedef pair<ll,ll> P;
typedef long double ld;
#define mem(x) memset(x, 0, sizeof(x))
#define me(x) memset(x, -1, sizeof(x))
#define fo(i,n) for(i=0; i<n; i++)
#define sc(x) scanf("%I64d", &x)
#define sca(n,m) scanf("%I64d%I64d", &n, &m)
#define pr(x) printf("%I64d\n", x)
#define pri(x) printf("%I64d ", x)
#define lowbit(x) x&-x
const ll MOD = 1e9 + 7;
const ll oo = 1e18;
const ll N = 4e5 + 5;
ll vis[N], a[N];
int main()
{
    ll i, j ,k;
    ll n, m, t, x;
    //cout<<(ll)pow(2,18)<<endl;

    cin>>t;
    while(t--)
    {
        cin>>n;
        mem(a);
        ll ans=0;
        for(i=2; i<=n; i++)
        {
            if(i%2)
            {
                k=0;x=i;
                while(1)
                {
                    if(x%2==0)
                    {
                        //k++;
                        break;
                    }
                    x>>=1;
                    k++;
                }
                k=1<<k;
                if(k<=n) a[i]=k;
                else a[i]=1, ans++;
            }
        }
        cout<<ans<<endl;
        for(i=2; i<n; i++)
        {
            if(a[i]<=1) cout<<1<<" ";
            else cout<<a[i]<<" ";
        }
        if(a[n]<=1) cout<<1<<endl;
        else cout<<a[n]<<endl;
    }

    return 0;
}

1007 Just an Old Puzzle

题意:15数码归位问题,给点初始状态,求120步之内是否可以归位

分析:

1.如果题目是求最短路径,可以用bfs或A*算法,但15个的状态太多也不会写

2.所以这道题其实很难

3.但是队友的书上正好有数码归位问题的结论(!):将数码排列一行,目标状态逆序对数目的奇偶性与初始状态一致则有解

4.由于每一步最多衍生出3种状态,3^120 >> 16! ,所以有解保证120步可达

跟题目一样迷的题解:

1007. Just an Old Puzzle

The solution consists of three steps.

//大概有三个步骤

At first you have to match the numbers 1, 2, 3 and 4.

//1.匹配1 .2 .3 .4

To match these numbers, we only need the positions of 1, 2, 3, 4 and empty grid.

//匹配这四个,需要知道1.2.3.4和空格的位置

So the total number of possible states are P_16^5=524160.

//这总共有16^5=524160种状态

You can use BFS or any algorithms to find it.

//这个范围内允许可以用BFS或其他算法得到其归位的最小步数

Next, you have to match the numbers 5, 6, 7 and 8.

//2.同理,匹配5.6.7.8

And at last, you have to match the numbers 9~15.

//3.匹配9~15

The total possible statuses are 8! = 40320.

//总共8! = 40320种状态

You can check if you could find the solution by checking the parity of inversion number of input permutation.

// ??突然跳跃)可以通过判断逆序对数目的奇偶性求解

You can easily prove that in first step, the maximum distance to target status are 46.

By using similar way, you can prove that you can match the grid in 120 moves.

//易证,第一步最多要46步,同理可证120步之内还原是ok的

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=16;
int ar[N],a[N];
int lowb(int t)
{
    return t & (-t) ;
}
void add(int i, int v)
{
    for ( ; i < N; ar[i] += v, i += lowb(i));
}
int sum(int i)
{
    int s = 0;
    for ( ; i > 0; s += ar[i], i -= lowb(i));
    return s;
}
int main()
{
    int n,m,T;
    scanf("%d",&T);
    while(T--)
    {
        n=4,m=4;
        int x,y,t,s=0,nu=0;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++)
            {
                scanf("%d",&t);
                if(t==0)
                    x=i,y=j;
                else
                    a[nu++]=t;
            }
        memset(ar,0,sizeof(ar));
        for(int i=nu-1;i>=0;i--)
        {
            s+=sum(a[i]-1);
            add(a[i],1);
        }
        if(m&1)
            if(s&1)puts("No");
            else   puts("Yes");
        else
            if(((n-x)^s)&1) puts("No");
            else   puts("Yes");
    }
    return 0;
}

1010 Minimal Power of Prime

题意:给定T组数据(T<=50000)n(n<=1e18),求将n唯一分解后质因子的最低指数;

分析:

1. 数学,贪心

2. 分析质因子的数量级: 1e18 = 1e9*1e9 ,若1e9之内没有质因子 ,则剩下的指数一定为1,(否则就超过1e18了),1e9太大会超时

3.继续分析:1e18 = 1e6*1e6*1e6 = 1e7*1e7*(1e4) = 1e8*1e8*(1e2) ,若1e6之内没有质因子 ,则剩下的指数一定为1或2,遍历1e6后若未完全分解根据剩下的是不是完全平方数判断结果(只能是1或2),T太大会超时

4.继续分析:1e18 = 1e4*1e4*1e4*1e4*1e2 = 1e5*1e5*1e5*1e3 = (p1:1e4*1e4)*(p2:1e4*1e4) = (p1:1e5*1e5)*(p2:1e5) ,若1e6之内没有质因子 ,则剩下的指数一定为1或2,3,4, 分别判断开根后是否为整数,有两个质因子的情况最低指数只能是1或2,判断是否能完全平方即可,比赛时感觉两个质因子的情况太复杂就没继续分析下去,结果发现因为是求最低指数所以多个大质因子结果只能是1或2反而判起来很简单orz,人蠢不能复聪

5.开方由于数字特别大要用powl()计算减少误差,而且两个参数必须强制转换成long double(常数也要,因为默认是double),也可以二分求开方结果 ,由于精度误差一般都在 +1~-1之内,也可以直接把结果p,p-1,p+1都判断是不是完全开方因子

题解:

1010. Minimal Power of Prime

Let‘s first factorize N using prime numbers not larger than N1/5. And let‘s denote M as the left part, all the prime factors of M are larger than N1/5. If M=1 then we are done, otherwise M can only be P2, P3, P4 or P2*Q2, here P and Q are prime numbers.

(1) If M1/4 is an integer, we can know that M=P4. Update answer using 4 and return.

(2) If M1/3 is an integer, we can know that M=P3. Update answer using 3 and return.

(3) If M1/2 is an integer, we can know that M=P2 or M=P2*Q2. No matter which situation, we can always update answer using 2 and return.

(4) If (1)(2)(3) are false, we can know that answer=1.

Since there are just O(N1/5/log(N)) prime numbers, so the expected running time is O(T*N1/5/log(N)).

代码:

#include<bits/stdc++.h>

#define fi first
#define se second
#define rep( i ,x ,y ) for( int i= x; i<= y ;i++ )
#define reb( i ,y ,x ) for( int i= y; i>= x ;i-- )
#define mem( a ,x ) memset( a ,x ,sizeof(a))
using namespace std;

typedef long long ll;
typedef long double ld;
typedef pair<int ,int> pii;
typedef pair<ll ,ll> pll;
typedef pair<string ,int> psi;

const int inf = 0x3f3f3f3f;
const int N = 10005;
const int M = 200050;

int T ,ans ,tot=0;
int unprime[N];
ll n ,prime[N];

void euler( ){
    unprime[1] = 1;
    rep( i ,1 ,N ){
        if( !unprime[i] )prime[++tot] = i;
        rep( j ,1 ,tot ){
            if( i*prime[j] >N )break;
            unprime[ i*prime[j] ] = 1;
            if( i%prime[j] == 0 )break;
        }
    }
}

int main( ){
    scanf("%d" ,&T );
    euler( );
    //cout<<tot<<endl;
    while( T-- ){
        ans = inf;
        scanf( "%lld" ,&n );
        //cout<<n<<endl;
        rep( i ,1 ,tot ){
            if( n%prime[i]==0 ){
                int tmp = 0;
                while( n%prime[i] ==0 ){
                    n /= prime[i];
                    tmp++;
                }
                ans = min( ans ,tmp );
            }
            if( n==1 )break;
        }

        if( n >= N ){
            ll p1 ,p2 ,p3 ;
            ll p11 ,p22 ,p33;
            ll pp1 ,pp2 ,pp3;
            ld s = n;
            p1 = powl( s ,(ld)1.0/4.0 );
            p11 = p1+1; pp1 = p1-1;
            p2 = powl( s ,(ld)1.0/3.0 );
            p22 = p2+1; pp2 = p2-1;
            p3 = sqrt( (ld)s );
            p33 = p3+1; pp3 = p3-1;
            //cout<<p1<<" "<<p2<<" "<<p3<<endl;
            //cout<<ans<<endl;
            if( n == p1*p1*p1*p1 || n == p11*p11*p11*p11 || n == pp1*pp1*pp1*pp1 ){ ans = min(ans ,4 );}
            else if( n == p2*p2*p2 || n == p22*p22*p22 || n == pp2*pp2*pp2 ){  ans = min( ans ,3 );}
            else if( n == p3*p3 || n == p33*p33 || n == pp3*pp3 ){ ans = min( ans ,2 );}
            else ans = min( ans ,1 );
        }

        printf("%d\n" ,ans );
    }
    return 0;
}

原文地址:https://www.cnblogs.com/-ifrush/p/11282176.html

时间: 2024-08-01 22:26:13

2019 hdu 第四场补题 (1 ,签到题的相关文章

acm集训训练赛A题【签到题】

一.题目 Description After winning gold and silver in IOI 2014, Akshat and Malvika want to have some fun. Now they are playing a game on a grid made of nhorizontal and m vertical sticks. An intersection point is any point on the grid which is formed by t

2019模拟赛09场解题报告

目录 2019模拟赛09场解题报告 目录la~~ 题一:瞬间移动 题二:食物订购 题三:马蹄印 题四:景观美化 2019模拟赛09场解题报告 标签(空格分隔): 解题报告 Forever_chen 2019.8.20 目录la~~ 题一:瞬间移动 [题面] 有一天,暮光闪闪突然对如何将一个整数序列a1,a2,...,an排序为一个不下降序列起了兴趣.身为一只年轻独角兽的她,只能进行一种叫做"单元转换"(unit shift)的操作.换句话说,她可以将序列的最后一个元素移动到它的起始位置

HDU 5003 Osu!(鞍山网络赛G题)

HDU 5003 Osu! 题目链接 就一签到题,排序之后for一遍计算出答案即可 代码: #include <cstdio> #include <cstring> #include <iostream> #include <string> #include <vector> #include <set> #include <map> #include <algorithm> #include <cmat

洛谷P3601签到题(欧拉函数)

题目背景 这是一道签到题! 建议做题之前仔细阅读数据范围! 题目描述 我们定义一个函数:qiandao(x)为小于等于x的数中与x不互质的数的个数. 这题作为签到题,给出l和r,要求求. 输入输出格式 输入格式: 一行两个整数,l.r. 输出格式: 一行一个整数表示答案. 输入输出样例 输入样例#1: 233 2333 输出样例#1: 1056499 输入样例#2: 2333333333 2333666666 输出样例#2: 153096296 说明 对于30%的数据,. 对于60%的数据,.

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 Multi-University Training Contest 4 补题链接:2019 Multi-University Training Contest 4 1001 AND Minimum Spanning Tree (HDU 6614) 题意 给定一个有 \(N\) 个结点的完全图,编号从 \(1\) 到 \(N\).结点 \(x\) 与结点 \(y\) \((1\leq x, y\leq N, x \neq y)\) 的边的权值为 \(x\) 与 \(y\) 按位与的值,求

2019湖南多校第四场

解题过程 开场lfw过A,然后shl过C,然后把B题丢给做苦力劳动悲悲伤伤的lfw写,lfw过B,D题lfw开始字符串hash,一开始直接用结构体里面存数组丢set里面然后MLE,之后改成long long丢进set,还是MLE,然后lfw开始上头,随便乱改一下就交上去MLE. 然后shl吧防AK题K过了,做过这套题的原题,接下来shl还是死磕I题,一直在WA.lfw修改了D题复杂度,WA了一发,改成双关键字就过了.最后 set只能存1e6,超过就会mle.shl把G题过掉,和byf一起死磕I题

[hdu 4899]14年多校第四场C Hero meet devil 状压DP

Time Limit: 16000/8000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Total Submission(s): 122    Accepted Submission(s): 49 Problem Description There is an old country and the king fell in love with a devil. The devil always asks th

2014多校第四场1005 || HDU 4901 The Romantic Hero (DP)

题目链接 题意 :给你一个数列,让你从中挑选一些数组成集合S,挑另外一些数组成集合T,要求是S中的每一个数在原序列中的下标要小于T中每一个数在原序列中下标.S中所有数按位异或后的值要与T中所有的数按位与的值相同,问能找出多少符合要求的组合. 思路 :比赛的时候有点没有头绪,后来二师兄想出了状态转移方程,YN又改了很多细节,最后才A的.总之是个别扭的DP..... 一开始是 _xor[i][j^a[i]] += _xor[i-1][j] :j 的下一个状态 就是异或上a[i],这个数组所代表的意思