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");
}
}