2020牛客多校第四场

B 分解质因子


basic gcd problem
题意:
给你一个公式…
思路:
可以看出公式表示的是c的多少多少次方,gcd最好情况是每次都消一个质因子,所以答案为c^(n的质因子个数)

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const ll mod=(ll)1e9+7;
ll tc,n,c;
ll quickmod(ll a, ll b, ll mod){
    ll ans=1;
    while(b>0){
        if(b&1) ans=ans*a%mod;
        a=a*a%mod;
        b/=2;
    }
    return ans;
}
int main() {
    ios::sync_with_stdio(false);cin.tie(0);cout.precision(10);cout << fixed;
#ifdef LOCAL_DEFINE
    freopen("input.txt", "r", stdin);
#endif
    cin>>tc;
    while(tc--){
        cin>>n>>c;
        int p=n;
        vector< pair<int, int> > pref;
        ll sum=0;
        for(int i=2; i*i<=p; ++i){
            if(p%i==0){
                int cnt=0;
                while(p%i==0){
                    p/=i;
                    ++cnt;
                    ++sum;
                }
                pref.emplace_back(make_pair(i, cnt));
            }
        }
        if(p>0) {
            ++sum;
            pref.emplace_back(make_pair(p, 1));
        }
        sum%=mod;
        cout<<quickmod(c, sum, mod)<<'\n';
    }
#ifdef LOCAL_DEFINE
    cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
    return 0;
}

F 签到


finding the order
题意:
有两条平行的直线ab,cd,给你ac,ad,bc,bd的距离,问你ab∥cd还是ab∥dc。
思路:
找这四个值的最大值。
如果最大值来自于ad或者bc,就是ab∥cd,否则是ab∥dc。

#include <bits/stdc++.h>
using namespace std;
int tc,ac,ad,bc,bd;
int main() {
    ios::sync_with_stdio(false);cin.tie(0);cout.precision(10);cout << fixed;
#ifdef LOCAL_DEFINE
    freopen("input.txt", "r", stdin);
#endif
    cin>>tc;
    while(tc--){
        cin>>ac>>ad>>bc>>bd;
        int temp=max({ac,ad,bc,bd});
        if(temp==ad || temp==bc){
            cout<<"AB//CD"<<'\n';
        } else{
            cout<<"AB//DC"<<'\n';
        }
    }
#ifdef LOCAL_DEFINE
    cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
    return 0;
}

H 组最多组gcd


harder gcd problem
题意:
从1~n选尽可能多组pair,他们的gcd都是大于1。
思路:
p*2>n的p不能匹配。
倒叙枚举(小于等于n/2的第一个质数)n个每个质因子,然后考虑他的所有小于n的倍数。
如果数量为奇数,因为肯定>1,所以2*x拿出来,其他的组。
如果数量是偶数,直接组。
最后把2*x的那些再拿出来组一组。

#include <bits/stdc++.h>
using namespace std;
const int N=2*(int)1e5+100;
int tc,n,vis[N],prime[N];
bool visit[N];
int num;
void init_prime(){
    memset(visit, true, sizeof(visit));
    num=0;
    int n=200000;
    for(int i=2; i<=n; ++i){
        if(visit[i]==true) prime[++num]=i;
        for(int j=1; j<=num && i*prime[j]<=n; ++j){
            visit[i*prime[j]]=false;
            if(i%prime[j]==0)break;
        }
    }
}
int main() {
    ios::sync_with_stdio(false);cin.tie(0);cout.precision(10);cout << fixed;
#ifdef LOCAL_DEFINE
    freopen("input.txt", "r", stdin);
#endif
    init_prime();
    cin>>tc;
    while(tc--){
        cin>>n;
        vector<int> two;
        vector< pair<int, int> > ans;
        memset(vis,0,sizeof(vis));
        int p=upper_bound(prime+1, prime+1+num, n/2)-prime-1;
        for(int i=p; i>=1; --i){
            int now=prime[i];
            vector<int> res;
            for(int j=1; j*now<=n; ++j){
                if(vis[j*now]==1) continue;
                res.emplace_back(j*now);
                vis[j*now]=1;
            }
            if(int(res.size())%2==0){
                for(int i=0; i<int(res.size()); i+=2) ans.emplace_back(make_pair(res[i], res[i+1]));
            } else{
                ans.emplace_back(make_pair(res[0], res[2]));
                two.emplace_back(res[1]);
                for(int i=3; i<int(res.size()); i+=2){
                    ans.emplace_back(make_pair(res[i], res[i+1]));
                }
            }
        }
        int len=int(two.size());
        if(len&1) --len;
        for(int i=0; i<len; i+=2){
            ans.emplace_back(make_pair(two[i], two[i+1]));
        }
        cout<<int(ans.size())<<'\n';
        for(pair<int, int> pii:ans){
            cout<<pii.first<<' '<<pii.second<<'\n';
        }
    }
#ifdef LOCAL_DEFINE
    cerr << "Time elapsed: " << 1.0 * clock() / CLOCKS_PER_SEC << " s.\n";
#endif
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值