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;
    }
  • 相关阅读:
    python--网络通信协议
    python--网络编程之socket
    python--内置函数03
    在Mapper中sql语句字段与实体类属性名字之间的关系
    网站引入QQ登录
    子类继承父类时构造函数的相关问题
    java中字符串比较的问题
    Mybatis中一对多与多对一的配置
    Spring中的依赖注入(1)
    P1618 三连击(升级版)
  • 原文地址:https://www.cnblogs.com/zbtrs/p/7887051.html
Copyright © 2011-2022 走看看