质因数专题

A题:
链接:https://www.luogu.com.cn/problem/B3715?contestId=160074
思路:太简单了,就不说了,直接放代码,嘿嘿~
代码:

#include<bits/stdc++.h>
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)

using namespace std;

int add(int x, int y){return x ? add((x & y) << 1, x ^ y): y;}

#define ONLINE_JUDGE

typedef long long ll;
int t;
ll n;

int main()
{
#ifndef ONLINE_JUDGE
    freopen("1.in", "r", stdin);
    freopen("1.out", "w", stdout);
#endif
    ios;
    cin>>t;
    while(t--)
    {
        cin>>n;
        for(ll i=2;i*i<=n;i++)
        {
            while(n%i==0)
            {
                n/=i;
                cout<<i<<" ";
            }
        }
        if(n>1)
        {
            cout<<n;
        }
        cout<<"\n";
    }

    return 0;
}

B题:
链接:https://www.luogu.com.cn/problem/UVA10976?contestId=160074
思路:
最开始我的思路是从n+1开始枚举,去计算当前枚举值与n的最大公因数是是多少,求得最小公倍数,然后再计算将n放大到最小公倍数需要的倍数与当前枚举值需要的倍数,其倍数之差即使即使答案,但此时的答案可能不符合要求,因为所需的答案的分子为1,而当前值的分子不一定为1,因此还要判断最小公倍数能否整除倍数之差,但是TLE了。因此需要采用更为简单的做法。
首先将x设为(k+a),y设为(k+b)(为什么是(k+a)与(k+b)请自己思考)则1/k=1/(k+a)+1/(k+b),经过通分转换之后得到结果k^2=a*b(请自己计算通分过程,这里写比较麻烦,哈哈),得到这个结论之后我们就可以去枚举a和b来计算x和y了。
代码:

#include<bits/stdc++.h>
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)

using namespace std;

int add(int x, int y){return x ? add((x & y) << 1, x ^ y): y;}

#define ONLINE_JUDGE

const int N=1e4+10;
int n;
struct node
{
    int x,y;
}a[N];

int main()
{
#ifndef ONLINE_JUDGE
    freopen("1.in", "r", stdin);
    freopen("1.out", "w", stdout);
#endif
    ios;
    while(cin>>n)
    {
        int ans=0,cnt=0;
        int k=n*n;
        for(int i=1;i<=n;i++)
        {
            if(k%i==0)
            {
                a[++cnt].x=k/i;
                a[cnt].y=i;
            }
        }
        cout<<cnt<<"\n";
        for(int i=1;i<=cnt;i++)
        {
            cout<<"1/"<<n<<" = 1/"<<n+a[i].x<<" + 1/"<<n+a[i].y<<"\n";
        }
    }

    return 0;
}

C题:
链接:https://www.luogu.com.cn/problem/AT_abc169_d?contestId=160074
思路:ljw已经有一篇题解了,我就不具体写了,我和他的思路是一样的,ljw题解链接:https://www.luogu.com.cn/article/mwbvn6np
代码:

#include<bits/stdc++.h>
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)

using namespace std;

int add(int x, int y){return x ? add((x & y) << 1, x ^ y): y;}

#define ONLINE_JUDGE

typedef long long ll;
const int N=1e6+10;
ll n;
int ans;

int main()
{
#ifndef ONLINE_JUDGE
    freopen("1.in", "r", stdin);
    freopen("1.out", "w", stdout);
#endif
    ios;
    cin>>n;
    for(ll i=2;i*i<=n;i++)
    {
        int res=0;
        if(n%i==0)
        {
            while(n%i==0)
            {
                n/=i;
                res++;
            }
        }
        int sum=0;
        for(int j=1;sum+j<=res;j++)
        {
            ans++;
            sum+=j;
        }
    }
    if(n>1)
    {
        ans++;
    }
    cout<<ans<<"\n";
    return 0;
}

D题:
链接:https://www.luogu.com.cn/problem/CF1062B?contestId=160074
思路:这道题先开平方还是先乘上一个数对于最终结果是一样的。看到这道题很容易想到最小的数就是质因子相乘,因此我们仅需要想办法让每个质因子仅有一个就行。题目中能够消去质因子的幂次方的操作就是开平方,因此很容易想到将每一个数的幂次方转化为2的k次,由于题目要求操作次数是最少的因此我们因该将幂次方转化为第一个大于原先幂次方的2的k次,然后不断开平方将数削成最小。
代码:

#include <bits/stdc++.h>
#define ios                      \
    ios::sync_with_stdio(false); \
    cin.tie(0);                  \
    cout.tie(0)

using namespace std;

int add(int x, int y) { return x ? add((x & y) << 1, x ^ y) : y; }

#define ONLINE_JUDGE

int n, cnt;
int a[1000000], t[1000000];

int main()
{
#ifndef ONLINE_JUDGE
    freopen("1.in", "r", stdin);
    freopen("1.out", "w", stdout);
#endif
    ios;
    cin >> n;
    int val=n;
    int maxx = 0;
    for (int i = 2; i * i <= n; i++)
    {
        int k = 0;
        if (n % i == 0)
        {
            a[++cnt] = i;
            while (n % i == 0)
            {
                n /= i;
                k++;
            }
            t[cnt] = k;
            maxx = max(maxx, k);
        }
    }
    if (n > 1)
    {
        a[++cnt] = n;
        maxx = max(maxx, 1);
    }
    int ans = 1, res = 0;
    while (ans < maxx)
    {
        ans *= 2;
        res++;
    }
    if (ans > maxx)
    {
        res++;
    }
    else
    {
        for (int i = 2; i <= cnt; i++)
        {
            if (t[i] != t[i - 1])
            {
                res++;
                break;
            }
        }
    }
    int num = 1;
    for (int i = 1; i <= cnt; i++)
    {
        num *= a[i];
    }
    if(num==val)
    {
        cout<<num<<" 0\n";
        return 0;
    }
    cout << num << " " << res << "\n";
    return 0;
}

E题:
链接:https://www.luogu.com.cn/problem/AT_abc215_d?contestId=160074
思路:
很明显对于每一个满足条件的k其与序列中任何一个数不会有公因子,因此仅需要记录序列中每一个数的因此,枚举1到m,看是否能够整除即可。
代码:

#include<bits/stdc++.h>
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)

using namespace std;

int add(int x, int y){return x ? add((x & y) << 1, x ^ y): y;}

#define ONLINE_JUDGE

const int N=1e5+10;
int n,m,cnt,kk;
int a[N],ans[N],f[N];
bool flag[N];

int main()
{
#ifndef ONLINE_JUDGE
    freopen("1.in", "r", stdin);
    freopen("1.out", "w", stdout);
#endif
    ios;
    cin>>n>>m;
    int res=0;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        if(!flag[a[i]]&&a[i]!=1)
        {
            ans[++cnt]=a[i];
        }
        flag[a[i]]=1;
        for(int j=2;j*j<=a[i];j++)
        {
            if(a[i]%j==0)
            {
                if(!flag[j])
                {
                    ans[++cnt]=j;
                }
                if(!flag[a[i]/j])
                {
                    ans[++cnt]=a[i]/j;
                }
                flag[j]=flag[a[i]/j]=1;
            }
        }
    }
    for(int i=1;i<=m;i++)
    {
        int flag1=1;
        for(int j=1;j<=cnt;j++)
        {
            if(i%ans[j]==0)
            {
                flag1=0;
                break;
            }
        }
        if(flag1)
        {
            f[++kk]=i;
        }
    }
    cout<<kk<<"\n";
    for(int i=1;i<=kk;i++)
    {
        cout<<f[i]<<"\n";
    }
    return 0;
}

F题:
链接:https://www.luogu.com.cn/problem/AT_abc114_d?contestId=160074
思路:
计算n的因子数的计算公式为(1+a1)(1+a2)(1+a3)……(1+an),其中ai代表质因子的幂次方(为什么可以自己推一下,很简单),而75进行质因子分解后为3 * 5 * 5,也就是说只有幂次方大于2的质因子才对结果有贡献,但是,75并不一定是严格的分为3 * 5 * 5,还有可能分为1 * 75,3 * 25,5 * 15这三种情况,因此需要将这四种情况一起计算。接下来的计算就是组合数学的回合了,有好长一串,我就不打了,嘿嘿。
代码:

#include<bits/stdc++.h>
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)

using namespace std;

int add(int x, int y){return x ? add((x & y) << 1, x ^ y): y;}

#define ONLINE_JUDGE

int n;
int a[110],ans[110];

int main()
{
#ifndef ONLINE_JUDGE
    freopen("1.in", "r", stdin);
    freopen("1.out", "w", stdout);
#endif
    ios;
    cin>>n;
    iota(a+1,a+n+1,1);
    for(int i=2;i*i<=n;i++)
    {
        for(int j=2;j<=n;j++)
        {
            while(a[j]%i==0)
            {
                a[j]/=i;
                ans[i]++;
            }
        }
    }
    for(int i=1;i<=n;i++)
    {
        if(a[i]>1)
        {
            ans[a[i]]++;
        }
    }
    int k1=0,k2=0,k3=0,k4=0,k5=0;
    for(int i=1;i<=n;i++)
    {
        if(ans[i]>=2)
        {
            k1++;
        }
        if(ans[i]>=4)
        {
            k2++;
        }
        if(ans[i]>=14)
        {
            k3++;
        }
        if(ans[i]>=24)
        {
            k4++;
        }
        if(ans[i]>=74)
        {
            k5++;
        }
    }
    cout<<k5+k4*(k1-1)+k3*(k2-1)+k2*(k2-1)*(k1-2)/2;
    return 0;
}

G题:
链接:https://www.luogu.com.cn/problem/CF1881D?contestId=160074
思路:
对于将ai替换为ai/x,aj替换为aj⋅x,对于整个序列的质因子的幂次方之和是没有影响的,而想要每个数都相等只需要让每一个质因子的幂次方平均分配给每一个数即可。
注意:本题的数据很容易超时,所以最好使用auto保证时间不会超时!!!
代码:

#include<bits/stdc++.h>
#define ios ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)

using namespace std;

int add(int x, int y){return x ? add((x & y) << 1, x ^ y): y;}

#define ONLINE_JUDGE

const int N=1e4+10,M=1e6+10;
int t,n;
int a[N];

int main()
{
#ifndef ONLINE_JUDGE
    freopen("1.in", "r", stdin);
    freopen("1.out", "w", stdout);
#endif
    ios;
    cin>>t;
    while(t--)
    {
        map<int,int> ans;
        cin>>n;
        int maxx=0;
        for(int i=1;i<=n;i++)
        {
            cin>>a[i];
            maxx=max(a[i],maxx);
            for(int j=2;j*j<=a[i];j++)
            {
                while(a[i]%j==0)
                {
                    ans[j]++;
                    a[i]/=j;
                }
            }
            if(a[i]>1)
            {
                ans[a[i]]++;
            }
        }
        int flag=1;
        for(auto &i : ans)
        {
            if(i.second%n)
            {
                cout<<"NO\n";
                flag=0;
                break;
            }
        }
        if(flag)
        {
            cout<<"YES\n";
        }
    }

    return 0;
}
posted @ 2024-02-28 21:59  黄金庭院第一码农樱  阅读(63)  评论(0)    收藏  举报