zoukankan      html  css  js  c++  java
  • vijos 小三学算术

    描述

    小三的三分球总是很准的,但对于数学问题就完全没有想法了,他希望你来帮他解决下面的这个问题:对于给定的n,从1!、2!、3!、……、n!中至少删去几个数,才可以使剩下的数的乘积为完全平方数?

    格式

    输入格式

    仅一行,包含一个整数n(1≤n≤500)。

    输出格式

    第一行包含一个整数k,表示最少需要删去的数字个数。

    接下来一行,从小到大排列的k个[1,n]之间的整数,给出删数的方案。如果方案不止一种,输出方案从小到大排序序列最小的一组即可。

    样例1

    样例输入1

    5

    样例输出1

    2
    2 5

    限制

    各个测试点1s

    提示

    样例说明:去掉2!和5!,剩下的是4!、3!和1!,它们的乘积为4!×3!×1!=24×6=144。

    分析:数学一本通上一本非常神的题.先对每个数分解质因数,如果一个数是完全数,那么它的所有质因子的次数一定要是偶数,这样的话很难操作,没有什么特别好的方法.尝试搜索,因为不知道要删掉几个数,可以用迭代深搜,可能会惊奇地发现自己过了,因为这道题有一个结论:答案不超过3.

          先把阶乘两两分组,(1*2!)*(3!*4!)*(5!*6!)......每一组前面的数会被后面的数所覆盖,这些数的质因子的次数一定是偶数,那么把每一组对答案有影响的数给提出来:2*4*6*......再提一个2出来:

    2*(1*2*3*......)=2!*(n/2)!那么删掉这两个阶乘就好了.这是n为偶数的情况,如果n为奇数,那么就把最后单独的那一个给删掉,然后就变成了偶数的情况,所以最多删3个数.

    奇偶性的转换可以利用异或运算来实现.不过代码有缺陷,质因子个数可能会大于300.自己改不动了......

    #include <cstdio>
    #include <cmath>
    #include <map>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    typedef long long ll;
    
    ll n, maxn, use[510], prime[510], vis[510], tot, sta[510], tsta, staa[510];
    ll num[50], ans[50];
    bool flag = false;
    //位运算
    
    void dfs(ll dep, ll maxx, ll nowsta, ll num)
    {
        if (dep == n + 1 || num == maxx + 1)
        {
            if (nowsta == 0)
            {
                for (ll i = 1; i <= maxx; i++)
                    ans[i] = use[i];
                flag = 1;
            }
            return;
        }
        ll temp = nowsta ^ sta[dep];
        dfs(dep + 1, maxx, nowsta, num);
        use[num] = dep;
        dfs(dep + 1, maxx, temp, num + 1);
    }
    
    void init()
    {
        for (ll i = 2; i <= 500; i++)
        {
            if (!vis[i])
                prime[++tot] = i;
            for (ll j = 1; j <= tot; j++)
            {
                ll t = prime[j] * i;
                if (t > 500)
                    break;
                vis[t] = 1;
                if (i % prime[j] == 0)
                    break;
            }
        }
    }
    
    int main()
    {
        init();
        scanf("%lld", &n);
        for (ll i = 1; i <= n; i++)
        {
            ll x = i;
            for (ll j = 1; j <= 64; j++)
            {
                ll p = 0;
                while (x && x % prime[j] == 0)
                {
                    x /= prime[j];
                    p = (p + 1) % 2;
                }
                if (p == 1)
                    staa[i] |= (1LL << (j - 1));
            }
        }
        memcpy(sta, staa, sizeof(staa));
        for (ll i = 1; i <= n; i++)
            for (ll j = 1; j < i; j++)
                sta[i] ^= staa[j];
        for (ll i = 1; i <= n; i++)
        {
            if (i == 1)
                tsta = sta[i];
            else
                tsta ^= sta[i];
        }
        while (1)
        {
            maxn++;
            memset(use, 0, sizeof(use));
            dfs(1, maxn, tsta, 1);
            if (flag)
            {
                printf("%lld
    ", maxn);
                for (int i = 1; i <= maxn; i++)
                    printf("%lld ", ans[i]);
                break;
            }
        }
    
        return 0;
    }
  • 相关阅读:
    Construct Binary Tree from Preorder and Inorder Traversal
    Construct Binary Tree from Inorder and Postorder Traversal
    Maximum Depth of Binary Tree
    Sharepoint 2013 创建TimeJob 自动发送邮件
    IE8 不能够在Sharepoint平台上在线打开Office文档解决方案
    TFS安装与管理
    局域网通过IP查看对方计算机名,通过计算机名查看对方IP以及查看在线所有电脑IP
    JS 隐藏Sharepoint中List Item View页面的某一个字段
    SharePoint Calculated Column Formulas & Functions
    JS 两个一组数组转二维数组
  • 原文地址:https://www.cnblogs.com/zbtrs/p/7887051.html
Copyright © 2011-2022 走看看