数学一本通【数论】小三学算术

11 篇文章 0 订阅
1 篇文章 0 订阅

时间限制: 1 Sec 内存限制: 128 MB

题目描述:

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

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

输出:
第一行包含一个整数k,表示最少需要删去的数字个数。
接下来一行,从小到大排列的k个[1,n]之间的整数,给出删数的方案。如果方案不止一种,输出方案从小到大排序序列最小的一组即可。

思路:
刚开始想了一个假算法,就是根据对4取余来算
如果 n%4 == 0 就删去 (n/2)!
如果 n%2 == 0 就删去一个 2!和一个 (n/2)!

详细思路见代码1
这个思路只有64分 因为这个代码只有保证可行却没有保证是最优解
因为这个思路不知道怎么处理删掉的那些数产生的化学反应,也没办法保证不会存在另外几个数产生化学反应后得到的结果不会比当前所得解更优

例如 对于n=18
这个思路会输出 删掉 2! 和 9! , 然后发现2! * 9! = 7! * 16 * 9
所以n=18 时正解应该是 输出 7!

正解:
虽然上面代码不能保证最优解,但我们也已经根据上面代码发现了最坏的情况也就是输出三个数,所以对于每一个n的最坏情况就是输出三个数
所以我们可以暴力枚举(i) , (i,j) , (i,j,k) 来寻找最优解
实现过程很巧妙
我也不知道这叫什么方法 分组hash?
也没心情写。。。
qaq
不过这里真的很精华。。。
具体思路看代码2吧

代码1:

#include<bits/stdc++.h>
using namespace std;
const int N=1e3+15;
typedef long long ll;
int main()
{
    ll n;
    cin>>n;
    if(n==1)
    {
        cout<<"0"<<endl;
        cout<<endl;
        return 0;
    }
    if(n%4==0)
    {
        cout<<"1"<<endl;
        cout<<(n/2)<<endl;
        return 0;
    }
    if(n%2==0)
    {
        if(n==2)
        {
            cout<<"1"<<endl;
            cout<<"2"<<endl;
            return 0;
        }
        cout<<"2"<<endl;
        cout<<"2 "<<(n/2)<<endl;
    }
    if(n%4==1)
    {
        cout<<"2"<<endl;
        cout<<(n/2)<<" "<<n<<endl;
        return 0;
    }
    if(n%4==3)
    {
        if(n==3)
        {
            cout<<"2"<<endl;
            cout<<"2 3"<<endl;
            return 0;
        }
        cout<<"3"<<endl;
        cout<<"2 "<<(n/2)<<" "<<n<<endl;
        return 0;
    }
    return 0;
}


代码2:

#include<bits/stdc++.h>
using namespace std;
const int N=1e3+15;
typedef long long ll;
bool vis[N];
ll prime[N],p[N],mp[N][2];
ll cnt=0;
void Prime()
{
    int n=500;
    vis[1]=1;
    for(int i=2;i<=n;i++)
    {
        if(!vis[i])
            prime[++cnt]=i;
        for(int j=1;j<=cnt&&i*prime[j]<=n;j++)
        {
            vis[i*prime[j]]=1;
            if(i%prime[j]==0)
                break;
        }
    }
   // cout<<cnt<<endl;
}
int main()
{
    Prime();
    ll n;
    p[0]=1;
    for(int i=1;i<=50;i++)
    {
        p[i]=p[i-1]*2;
    }
    cin>>n;
    for(int i=2;i<=n;i++)
    {
        ll x=i;
        for(int j=1;j<=50;j++)
        {
            int op=0;
            while(x%prime[j]==0)
            {
                op++;
                x/=prime[j];
            }
            if(op%2==1)
            {
                mp[i][0]^=p[j];
            }
        }
        for(int j=51;j<=95;j++)
        {
            int op=0;
            while(x%prime[j]==0)
            {
                op++;
                x/=prime[j];
            }
            if(op%2==1)
            {
                mp[i][1]^=p[(j-50)];
            }
        }
        mp[i][0]^=mp[i-1][0];
        mp[i][1]^=mp[i-1][1];
    }
    ll ans0=0,ans1=0;
    for(int i=2;i<=n;i++)
    {
        ans0^=mp[i][0]; ans1^=mp[i][1];
    }
   // cout<<ans0<<" "<<ans1<<endl;
    for(int i=2;i<=n;i++)
    {
        if(mp[i][0]==ans0&&mp[i][1]==ans1)
        {
            cout<<"1"<<endl;
            cout<<i<<endl;  return 0;
        }
    }

    for(int i=2;i<=n;i++)
    {
        for(int j=i+1;j<=n;j++)
        {
            if( (mp[i][0]^mp[j][0])==ans0 && (mp[i][1]^mp[j][1])==ans1 )
            {
                cout<<"2"<<endl;
                cout<<i<<" "<<j<<endl;  return 0;
            }
        }
    }

    for(int i=2;i<=n;i++)
    {
        for(int j=i+1;j<=n;j++)
        {
            for(int k=j+1;k<=n;k++)
            {
                if( (mp[i][0]^mp[j][0]^mp[k][0])==ans0 && (mp[i][1]^mp[j][1]^mp[k][1])==ans1 )
                {
                    cout<<"3"<<endl;
                    cout<<i<<" "<<j<<" "<<k<<endl;  return 0;
                }
            }
        }
    }
    return 0;
}

### 回答1: 信息学奥赛数学一本 pdf 是一本针对信息学竞赛中数学方面的教材。这本书主要围绕数学知识点、方法和技巧,特别是数论、图论、组合数学等方面,提供了详细的讲解和丰富的例题。对于想要提高信息学竞赛数学水平的人来说,这本书是一本非常好的参考书和练习书。 这本书中的内容主要分为四个部分:基础篇、提高篇、竞赛篇和知识点讲解。其中,基础篇介绍了数学中的基本概念和知识点,如数列、递归、平衡树等。提高篇则在此基础上进一步探讨了进阶的数学概念和应用,例如欧拉定理、杨表、背包等。竞赛篇则是以具体的例题为主,过多种类型和难度的竞赛题型,提供了实战测验和训练。最后的知识点讲解部分则对于一些比较细节的数学知识点进行了详细的解释和讲解,为读者提供了更深层次的数学理解。 总的来说,信息学奥赛数学一本 pdf 是一本以解题为导向的练习题库,尤其适合那些希望过信息学竞赛展示自己数学方面实力的读者。这本书不仅可以帮助读者掌握数学的基础知识,更可以锻炼读者的解题能力和应对高难度题目的能力。 同时,在信息学竞赛方面,具备出色数学素养的选手更容易取得好成绩。 ### 回答2: 信息学竞赛数学一本pdf是一份信息学竞赛相关的数学学习资料,它内容涉及很多数学知识,例如数论、组合数学、图论等等,并且可以帮助学生更好地掌握信息学竞赛中的数学问题。 本资料适合年龄较大的学生,学习难度较高,需要一定的数学基础。使用这份资料可以帮助学生提升数学思维能力,培养解决信息学问题的能力,更好地准备参加信息学竞赛。 此外,本资料也适合对数学感兴趣的学生学习。学习这份资料可以帮助学生更好地掌握数学知识,提高其数学解题能力,同时也可以激发他们的兴趣,让他们更愿意学习数学。 总之,在信息学竞赛方面,数学是重要的一部分,因此学习该pdf对于提高学生的信息学竞赛水平至关重要。同时,学习数学本身也是一个值得推崇的事情,无论是从个人发展还是社会进步的角度来看,学习数学都有着重要的作用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值