2016.07.12 完成 9 道题

本文解析了多个UVA在线编程比赛题目,包括求末位非零数字、因数分解等,采用不同算法策略解决问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

UVA-575

如题目所描述的方法求出值就好了。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string>
using namespace std;
string s;
int main () {
    freopen("xx.in","r",stdin);
    while (cin>>s){
        if (s == "0") break;
        int len = s.length();
        int sum = 0;
        for (int i = 0; i < len; i++){
            sum +=(s[i]-'0') * ((1<<(len - i))-1);
        }
        printf("%d\n",sum);
    }
}

UVA-10110

题意:这个人第 i 次走过去时会把所有 i 的倍数的灯都按一次开关。求走 n 次后,第 n 盏灯是开还是关。
解题思路:对于一个数,它每存在一个因数它就会被按一次。对于完全平方数以外的数字的因数都是成对的,就是偶数次按,最后必然是关着的。所以只要判断是不是完全平方数就好了。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
int n;
int main () {
    while (true) {
        long long s,m=0;
        scanf("%lld",&s);
        if (s == 0) break; 
        long long t = sqrt(s);
        if (t * t == s)  printf("yes\n");
         else printf("no\n");
    }
}

UVA-550

题意:给定m,k,n。其中 m 为 m进制,n为一个固定乘数, k 为m进制下某个数字的末尾。要求这个数字最小为几位。
解题思路: 假设这个m进制数字 为 xxxxxxxk
我们可以做出模拟 now = k * n ,t = now % m ,则t是xxxxxxxk * n 结果的最后一位,也就是xxxxxxxk 的倒二位。即xxxxxxtk 。同时还可能有一个进位 z。通过 (t * n + z)% m可以求到倒三位。依次推下去,统计求来几位,知道某一位与k 相同。此时的位数就是最小位数。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string>
using namespace std;
int m,k,n,la;
int main () {
    freopen("xx.in","r",stdin);
    while (scanf("%d%d%d",&m,&k,&n) != EOF){
        la=0;
        int now=k,x=0;
        while (now*n + x != k) {
            x = now*n + x;
            now = x % m;
            x = x / m;
            la++;
        }
        la++;
        printf("%d\n",la);
    }
}

UVA-568

题意:求 n! 中最后一位非零数字是多少。
解题思路:首先,因为零成任何数都是零,所以当最后一位出现0时就可以去掉了。然后,我们是不是只要保留最后一位能?不是这样的,因为最后一位可能乘上某个数就变成0了,就要知道它前面的是多少才能继续计算,如 32 × 5 = 160,末位是6,进了 1。保留6位就能解决了。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string>
using namespace std;
int n;
int main () {
    freopen("xx.in","r",stdin);
    while (scanf("%d",&n) != EOF) {
        long long ans=1;
        for (int i = 1; i <= n; i++) {
            ans = ans * i;
            while (ans % 10 == 0) ans/=10;
            ans = ans %  1000000;
        }
        while (ans % 10 == 0) ans/=10;
        ans=ans%10;
        printf("%5d -> %lld\n",n,ans);
    }
}

UVA-408

解题思路:判断2个数是不是互质。用辗转相除法就好了。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string>
using namespace std;
int gcd(int x, int y){
    if (y == 0) return x;
    else return gcd(y,x % y);
}
int main () {
    int n,m;
    freopen("xx.in","r",stdin);
    while (scanf("%d%d",&n,&m) != EOF){
        printf("%10d%10d    ",n,m);
        if (gcd(n,m) == 1) printf("Good Choice\n");
        else printf("Bad Choice\n");
        printf("\n");
    }
}

UVA-350

题意:给Z,I,M,L,求经过多少次 newL = ( z*l + i ) mod m 之后 newL会出现重复。
解题思路:暴力模拟,要注意最开始的 L 不一定就在newL的变化之中。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
int z,m,l,i;
int pd[300000];
int main () {
    int n=0;
    freopen("xx.in","r",stdin);
    while (true) {
        scanf("%d%d%d%d",&z,&i,&m,&l);
        memset(pd,0,sizeof (pd));
        if (z == 0) break;
        int now = z*l + i, cnt=1;
        now = now %m;
        pd[l] = 1;
        while ( !pd[now] ) {
            pd[now] = 1;
            now = z*now +i;
            now %=m;
            cnt++;

        }
        if (now != l)  cnt --;
        n++;
        printf("Case %d: %d\n",n,cnt);
    }
}

UVA-10061

题意:给出 N,B。求 N!在 B 进制下末尾有多少个 0 和有多少位。
解题思路: 对于任意m进制和十进制 S之间的位数关系,假设十进制转成B进制后有k位,就会有这样一个关系:
B^(k-1) <= S <=B^k。如果S = N!,那么就是 B^(k-1) <= N!<=B^k。以m为底取log。就会有∑log B i (i= 1 to n) <= k。因为c++只有默认以e或10 为底数的log函数,需要套换底公式。
关于有多少个0的问题,我们知道在10下面我们是看所有质因数中 2 和 5 能配出多少对就有多少个0,在B进制下也能通过求质因数的方式来判断有多少个0。我们只要知道B有哪些质因数,求 1~N中能获得多少这些质因数,计算一下就好了。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
int n,pi[300],lp,b,tot[300],z[300];
bool pd[900];
int main () {
    freopen("xx.in","r",stdin);
    while (scanf("%d%d",&n,&b)!=EOF){
        memset(pd,true,sizeof(pd));
        memset(pi,0,sizeof(pi));
        memset(tot,0,sizeof(tot));
        memset(z,0,sizeof(z));
        lp=0;
        for (int i = 2; i <= b; i++)
            if (b % i == 0 &&  pd[i]){
                pi[++lp] = i;
                for (int j = 1; i*j <= b; j++)
                    pd[i*j] =false;
            }
        double s=0.000000000000;
        for (int i = 1; i <= n; i++)
            s=s+log(i+0.0);
        s= s / log(b+0.0) +1e-8;
        int m = s;
        if (m < s) m++;
        for (int l = 1; l <= n; l++){
            int k = l;
            for (int i = 1; i <= lp; i++)
                while (k % pi[i] == 0  && k){
                    tot[i]++;
                    k/=pi[i];
                }
        }
        for (int i = 1; i <= lp; i++)
            while (b &&  b % pi[i] == 0) {
                z[i]++;
                b/=pi[i];
            }
        int sum = 999999999;
        for (int i = 1; i <= lp; i++) 
            sum = min(sum,tot[i]/z[i]);
        printf("%d %d\n",sum,m);
    }
}

UVA-10392

题意:求n的因数分解。
解题思路:因为题目保证最多只有一个大于1000000 的质因数,听说可以暴力不断从2开始跑,遇到能整除的就整除,然后在从2开始跑。
我这里是复习了下线性筛法求素数。然后也是拿一个素数,能整除时就一直除一直输出,不行换下一个,知道素数表完了,如果 n != 1 再把n输出来。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
bool pd[1001000];
int pi[80000],lp;
int main () {
    freopen("xx.in","r",stdin);
    lp=0;
    memset(pd,true,sizeof(pd));
    for (int i = 2; i < 1000000; i++) {
        if (pd[i]) pi[++lp] = i;
        for (int j = 1; j <= lp  &&  i*pi[j] < 1000000; j++) {
            pd[i*pi[j]] =false;
            if (i % pi[j] == 0) break;
        }
    }
    long long n;
    while (true) {
        scanf("%lld",&n);
        if (n == -1) break;
        for (int i = 1; i <= lp && pi[i] <= n; i++)
            while (n % pi[i] == 0  &&  n) {
                n/=pi[i];
                printf("    %d\n",pi[i]);
            }
        if (n != 1) printf("    %lld\n",n);
        printf("\n");
    }
}

UVA-10879

题意:把 n 写成 n = A * B = C * D 的形式,其中ABCD大于 1 。
解题思路: 其实不明白这题想干嘛。。。循环从2开始,遇到是n因数的就输出来。输完2个break循环就好了。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <string>
using namespace std;
int t,n;
int main () {
    scanf("%d",&t);
    for (int l = 1; l <= t; l++) {
        scanf("%d",&n);
        printf("Case #%d: %d ",l,n);
        int z=0;
        for (int i = 2; i < n; i++)
            if (n % i == 0) {
                printf("= %d * %d ",i,n/i);
                z++;
                if (z == 2) break;
            }
        printf("\n");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值