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

【HDU 6014】

SOLVED

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

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

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

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

              (就是多验)        

 

#include
#include
#include
#include
#include
#include<string>
#include
#include
#include
#include
#include<set>
#include
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";
    }
}
View Code

【HDU 6015】

UNSOLVED

 


【HDU 6016】

SOLVED

【题目大意】给数字N,要求将数字1~N分成k堆,每一堆的总和都相等,如果能则输出“yes”,并输出方案,如果不行输出“no”

【解题思路】

分类讨论

一种是n/k是偶数的,直接取头取尾然后分配就行,

一种是奇数,取前3k个,然后对后面剩余的取头取尾分配

 

(此处应有取前3k个可行的证明)

 

然后就是几个特判(程序要优美就不应该有特判)

当k==1时,输出全部

当1~N的总和不能整除k时,输出no

当k==n时输出no

 

 

#include
#include
#include
#define ll long long
using namespace std;
const int MAXN = 100010;
vector<int> ans[MAXN];
ll n, k;
void solve()
{
    if ((n*(n + 1) / 2) % k != 0 || (k == n&&k!=1))
    {
        printf("no\n");
        return;
    }
    ll d = n / k;
    printf("yes\n");
    if (k == 1)
    {
        for (int i = 1; i <= n; i++)
        {
            printf("%d", i);
            if (i != n)
                printf(" ");
            else
                printf("\n");
        }
        return;
    }
    if (d & 1)
    {
        ll sum =( (1 + 3*k)*3 / 2);
        //printf("sum  == %lld \n", sum);
        for (int i = 1; i <= k; i++)
        {
            ans[i].push_back(i);
        }
        int tot = k + 1;
        for (int i = k; i > 0; i -= 2)
        {
            ans[i].push_back(tot), tot++;
        }
        for (int i = k - 1; i > 0; i -= 2)
        {
            ans[i].push_back(tot), tot++;
        }
        for (int i = 1; i <= k; i++)
        {
            ans[i].push_back(sum - ans[i][0] - ans[i][1]);
        }
        tot = 1;
        ll d = ((n-3*k) / k)/2;
        for (int i = 1; i <= k; i++)
        {
            for (int j = 1; j <= d; j++)
                ans[i].push_back(3 * k + tot),ans[i].push_back(n + 1 - tot),tot++;
        }
        for (int i = 1; i <= k; i++)
        {
            for (int j = 0; j < ans[i].size(); j++)
            {
                printf("%d", ans[i][j]);
                if (j == ans[i].size() - 1)
                    printf("\n");
                else
                    printf(" ");
            }
        }
        for (int i = 1; i <= k; i++)
            ans[i].clear();
    }
    else
    {
        int cnt = 1;
        for (int i = 1; i <= k; i++)
        {
            for (int j = 0; j 2; j++)
            {
                printf("%d %d", cnt, n + 1 - cnt);
                if( j == (d / 2) - 1 )
                    printf("\n");
                else
                    printf(" ");
                cnt++;
            }
        }
    }
    return;
}
int main()
{
    int T;
    scanf("%d", &T);
    while (T--)
    {
        scanf("%lld%lld", &n,&k);
        solve();
    }
    return 0;
}
View Code

【HDU 6017】

UNSOLVED

 


【HDU 6018】

UNSOLVED

 


【HDU 6019】

UNSOLVED

 

 


【HDU 6020】

SOLVED

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

【思路】数字谜题的结论

 

#include
#include
#include
#include
#include
#include<string>
#include
#include
#include
#include
#include<set>
#include
#include
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];
            }
        }
    }
};
mapint>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";
    }
}
View Code

【HDU 6021】

UNSOLVED

 

 


【HDU 6022】

UNSOLVED

 

 


【HDU 6023】

SOLVED

【题目大意】

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

 

#include
#include
#include
#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;
}
View Code

 

转载于:https://www.cnblogs.com/rentu/p/11297739.html

你可能感兴趣的:(杭电多校(四)2019.7.31--暑假集训)