实训第二次上机(假的)题解 (Past)

10175101159 edited 3 年,8 月前

This is a past version of blog 实训第二次上机(假的)题解

ps:先写了前四题

$A$ 小明生日进制数位和均值

$Note:$
数据量不大,直接模拟
注意会爆$int$,$long long$大法好

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll T,n,up,dn,tmp;
ll i;
ll cal(ll num,ll base)
{
    ll ret=0;
    while(num){
        ret+=num%base;
        num/=base;
    }
    return ret;
}
int main()
{
    cin>>T;
    while(T--){
        cin>>n;
        up=0;
        for(i=2;i<n;++i)up+=cal(n,i);
        dn=n-2;
        tmp=__gcd(up,dn);
        cout<<up/tmp<<'/'<<dn/tmp<<endl;
    }
    return 0;
}

$B$ 邮件地址排序

$Note:$
结构体排序

#include<bits/stdc++.h>
using namespace std;
int n;
char c;
string tmp;
struct data{
    string s,t;
}a[1000000];
int i;
bool cmp(data a,data b)
{
    if(a.t!=b.t)return a.t<b.t;
    return a.s>b.s;
}
int main()
{
    cin>>n;
    getchar();
    for(i=0;i<n;++i){
        while(c=getchar()){
            if(c=='@')break;
            else tmp+=c;
        }
        a[i].s=tmp;
        tmp="";
        while(c=getchar()){
            if(c=='\n'||c==EOF)break;
            else tmp+=c;
        }
        a[i].t=tmp;
        tmp="";
    }
    sort(a,a+n,cmp);
    for(i=0;i<n;++i)cout<<a[i].s<<'@'<<a[i].t<<endl;
    return 0;
}

$C$ 遥远距离

$Note:$
结构体排序+高精度加减
这时候$C++$的$string$的优势就体现出来了
没用模板,手打的高精度,有点糙,凑合着用

#include<bits/stdc++.h>
using namespace std;
int n,tmp;
struct data{
    string s;
    bool flag;
    int num;
}a[50];
char b[126],c[126],d[126];
int i,j;
bool cmp(data a,data b)
{
    if(a.flag!=b.flag)return a.flag<b.flag;
    if(a.flag){
        if(a.num!=b.num)return a.num<b.num;
        return a.s<b.s;
    }
    if(a.num!=b.num)return a.num>b.num;
    return a.s>b.s;
}
int main()
{
    cin>>n;
    for(i=0;i<n;++i){
        cin>>a[i].s;
        a[i].num=a[i].s.length();
        if(a[i].s[0]=='-'){
            a[i].flag=1;
            a[i].s=a[i].s.substr(1,a[i].num-1);
            --a[i].num;
        }
    }
    sort(a,a+n,cmp);
    for(i=0;i<126;++i)b[i]=c[i]=d[i]='0';
    for(i=125,j=a[0].num-1;j>=0;--j)b[i--]=a[0].s[j];
    for(i=125,j=a[n-1].num-1;j>=0;--j)c[i--]=a[n-1].s[j];
    if(a[0].flag!=a[n-1].flag){
        if(a[0].s=="0"&&a[n-1].s=="0"){
            cout<<0;
            return 0;
        }
        bool cf=0;
        for(i=125;i>=0;--i){
            tmp=b[i]+c[i]-2*'0'+cf;
            if(tmp>9)d[i]=(char)(tmp-10+'0'),cf=1;
            else d[i]=char(tmp+'0'),cf=0;
        }
        for(i=0;;++i)if(d[i]!='0')break;
        for(j=i;j<126;++j)cout<<d[j];
    }
    else if(a[0].flag){
        if(a[0].s==a[n-1].s){
            cout<<0;
            return 0;
        }
        bool cf=0;
        for(i=125;i>=0;--i){
            tmp=c[i]-b[i]-cf;
            if(tmp<0)d[i]=(char)(tmp+10+'0'),cf=1;
            else d[i]=char(tmp+'0'),cf=0;
        }
        for(i=0;;++i)if(d[i]!='0')break;
        for(j=i;j<126;++j)cout<<d[j];
    }
    else{
        if(a[0].s==a[n-1].s){
            cout<<0;
            return 0;
        }
        bool cf=0;
        for(i=125;i>=0;--i){
            tmp=b[i]-c[i]-cf;
            if(tmp<0)d[i]=(char)(tmp+10+'0'),cf=1;
            else d[i]=char(tmp+'0'),cf=0;
        }
        for(i=0;;++i)if(d[i]!='0')break;
        for(j=i;j<126;++j)cout<<d[j];
    }
    return 0;
}

$D$ 幂次转换

$Note:$
第一眼看预处理质因数,但看到数据范围就怂了
后来想想$2^{64}>10^{18}$(要多刷题积累这种常见的数据大小)
所以直接遍历$base=2,3,…,64$,判断开$base$次根号是不是整数
这样时间复杂度就大大降低了,然后随便瞎写写都不会$TLE$
方法很多,二分查找或者利用类似判断是不是平方数的办法都可以

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
int T;
ll n;
bool jdg;
void cal(ll n,ll i)
{
    if(n<2)return;
    ll tmp=pow((ld)n,(ld)1.0/i)+0.5;
    ll rst=1;
    for(int j=0;j<i;++j)rst*=tmp;
    if(rst==n)cout<<'='<<tmp<<'^'<<i,jdg=0;
}
int main()
{
    cin>>T;
    while(T--){
        cin>>n;
        cout<<n;
        jdg=1;
        for(ll i=2;i<64;++i)cal(n,i);
        if(jdg)cout<<" is powerless.";
        cout<<endl;
    }
    return 0;
}

$E$ 变换种类数

$Note:$
还没想好思路,先留个坑