杭电数论入门习题
2016-07-05 21:28
423 查看
HDU 1973 Prime Path
这道题是一道从起点到终点的问题,很明显可以用广搜搜索最小步数即可,同理也可以用最短路,但是需要建边,时间复杂度低。#include <cstdio> #include <queue> #include <cmath> #include <cstdlib> #include <cstring> #include <iostream> using namespace std; const int maxn = 10005; bool prime[maxn],vis[maxn]; char a[5],b[5]; void init() //生成素数表,不然每次都判断很耗时 { memset(prime, false, sizeof(prime)); for(int i = 2; i < maxn; i++) if(!prime[i]) for(int j = i*i; j < maxn; j += i) prime[j] = true; } struct Node //这里我将整数当做字符串处理的,但是当整数处理可能操作会麻烦,但是时间更快 { char s[5]; int step; }; int bfs() { queue <Node> que; Node pre,cur; memset(vis, false, sizeof(vis)); memcpy(pre.s, a, sizeof(a)); //字符串复制函数 pre.step = 0; que.push(pre); vis[atoi(a)] = true; //atoi函数将字符串转化为整形 while(!que.empty()) { pre = que.front(); que.pop(); if(!strcmp(pre.s,b)) return pre.step; for(int i = 0; i < 4; i++) { for(int j = 0; j < 10; j++) { if(!i && !j) continue; //最高位不改为0 memcpy(cur.s, pre.s,sizeof(pre.s)); cur.s[i] = j + '0'; int temp = atoi(cur.s); if(!vis[temp] && !prime[temp]) { vis[temp] = true; cur.step = pre.step + 1; que.push(cur); } } } } return -1; } int main() { int T; scanf("%d", &T); init(); while(T--) { scanf("%s%s", a, b); int ans = bfs(); if(ans == -1) printf("Impossible\n"); else printf("%d\n", ans); } return 0; }
HDU 1930 And Now, a Remainder from Our Sponsor
这道题看着麻烦,其实写起来还是挺简单的,有一些小细节还是需要处理的,比如一个6位数如何分割问题,还要最后剩余可能一个空格,后者2个空格的处理问题,详细看代码。#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; char str[55][10]; int a[10],b[10],c[55]; void exgcd(int a, int b, int &x, int &y) { if(b == 0) { x = 1; y = 0; return; } exgcd(b, a % b, y, x); y -= (a/b)*x; } int CRT(int a[],int m[],int n) { int M = 1; int ans = 0; for(int i=0; i<n; i++) M *= m[i]; for(int i=0; i<n; i++) { int x, y; int Mi = M / m[i]; exgcd(Mi, m[i], x, y); ans = (ans + Mi * x * a[i]) % M; } if(ans < 0) ans += M; return ans; } int main() { int T,n; scanf("%d", &T); while(T--) { scanf("%d", &n); for(int i = 0; i < 4; i++) scanf("%d", &a[i]); for(int i = 0; i < n; i++) scanf("%d", &c[i]); for(int i = 0; i < n; i++) { for(int j = 3; j >= 0; j--) //倒着求 { b[j] = c[i]%100; c[i] /= 100; } int ans = CRT(b, a, 4); for(int j = 2 ; j >= 0; j--) { b[j] = ans%100; ans /= 100; } if(i != n-1) { for(int j = 0 ; j < 3; j++) if(b[j] == 27) printf(" "); else printf("%c", b[j]+'A'-1); } else //最后的空格处理问题 { if(b[2] == 27) { b[2] = 0; if(b[1] == 27) b[1] = 0; } for(int j = 0 ; j < 3; j++) if(b[j] == 27) printf(" "); else if(b[j]) printf("%c", b[j]+'A'-1); } } printf("\n"); } return 0; }
HDU 1920 Jackpot
水题,求最小公倍数#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; typedef long long LL; int a[5]; int main() { int n,m; while(scanf("%d", &n) != EOF) { while(n--) { scanf("%d", &m); for(int i = 1; i <= m; i++) scanf("%d", &a[i]); LL ans = 1,j; for(int i = 1; i <= m; i++) { for(j = 1; (j*ans)%a[i] != 0; j++); ans *= j; if(ans > 1000000000) break; } if(ans > 1000000000) printf("More than a billion.\n"); else printf("%I64d\n", ans); } } return 0; }
HDU 1788 Chinese remainder theorem again
这道题同样没什么难点,但是需要转化一下。N%M=(M-a)转化为(N+a)%M=0,因此同样成了求最小公倍数的问题。#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; typedef long long LL; int b[15]; int main() { int I,a; while(scanf("%d%d", &I, &a) != EOF) { if(!I && !a) break; for(int i = 1; i <= I; i++) scanf("%d", &b[i]); LL ans = 1,j; for(int i = 1; i <= I; i++) { for(j = 1; (ans*j)%b[i]; j++); ans *= j; } printf("%I64d\n", ans - a); } return 0; }
HDU 1787 GCD Again
#include <cmath> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; int euler(int n){ int m = (int)sqrt(n+0.5); int ans = n; for(int i = 2; i <= m; i++) if(n % i == 0){ ans = ans/i*(i-1); while(n % i == 0) n /= i; } if(n > 1) ans = ans/n*(n-1); return ans; } int main() { int N; while(scanf("%d", &N) != EOF && N) { int ans = euler(N); printf("%d\n", N-1-ans); } return 0; }
HDU 1452 Happy 2004
/* 设S(x)表示x的因子和。则题目求为:S(2004^X)mod 29 因子和S是积性函数,即满足性质1。 性质1 :如果 gcd(a,b)=1 则 S(a*b)= S(a)*S(b) 2004^X=4^X * 3^X *167^X S(2004^X)=S(2^(2X)) * S(3^X) * S(167^X) 性质2 :如果 p 是素数 则 S(p^X)=1+p+p^2+...+p^X = (p^(X+1)-1)/(p-1) 因此:S(2004^X)=(2^(2X+1)-1) * (3^(X+1)-1)/2 * (167^(X+1)-1)/166 167%29 == 22 S(2004^X)=(2^(2X+1)-1) * (3^(X+1)-1)/2 * (22^(X+1)-1)/21 性质3 :(a*b)/c %M= a%M * b%M * inv(c) 其中inv(c)即满足 (c*inv(c))%M=1的最小整数,这里M=29 则inv(1)=1,inv(2)=15,inv(22)=15 有上得: S(2004^X)=(2^(2X+1)-1) * (3^(X+1)-1)/2 * (22^(X+1)-1)/21 =(2^(2X+1)-1) * (3^(X+1)-1)*15 * (22^(X+1)-1)*18 */ #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const int mod = 29; int sum(int a,int b) //快速幂 { int ans = 1; while(b) { if(b&1) ans = (ans*a)%mod; a = (a*a)%mod; b = b>>1; } return ans; } int main() { int X; while(scanf("%d", &X) != EOF && X) { int a,b,c; a = (sum(2,2*X+1)-1); b = (sum(3,X+1)-1); c = (sum(167,X+1)-1); printf("%d\n", (a*b*15*c*18)%29); } return 0; }
HDU 1370 Biorhythms
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; int MOD = 21252; void exgcd(int a,int b,int &x,int &y) { if(b == 0) { x = 1; y = 0; } else { exgcd(b, a%b, y, x); y -= (a/b)*x; } } int CRT(int a[],int m[],int n) { int M = 1; int ans = 0; for(int i = 0; i < n; i++) M *= m[i]; for(int i = 0; i < n; i++) { int Mi = M/m[i]; int x,y; exgcd(Mi, m[i], x, y); ans = (ans + Mi*x*a[i])%M; } if(ans < 0) ans += M; return ans; } int main() { getchar(); int a[5],m[5] = {23, 28, 33}; int d,kase = 1; while(scanf("%d%d%d%d", &a[0], &a[1], &a[2], &d) != EOF) { if(a[0] == -1 && a[1] == -1 && a[2] == -1 && d == -1) break; int ans = CRT(a, m, 3); if(ans <= d) ans += MOD; printf("Case %d: the next triple peak occurs in %d days.\n", kase++, ans-d); } return 0; }
HDU 1299 Diophantus of Alexandria
这道题非常需要转化,假设y = (n+k),则x = n*(n+k)/k;若n = p1 ^ e1 * p2 ^ e2 ……….*pn ^ en,则n的质因子为sum ( n)= ( 1 + e1 ) ( 1 +e2 ) * ………* ( 1 +en ),则n*n则质因子为( 1 + 2*e1 ) * ( 1 +2*e2 ) * ………* ( 1 +2*en ),这样就可以求解了。#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; typedef long long LL; const int maxn = 4000; bool isprime[maxn]; int prime[maxn]; int init() { int cnt = 0; memset(isprime, 0, sizeof(isprime)); for(int i = 2; i < maxn; i++)if(!isprime[i]) for(int j = i*i; j < maxn; j += i) isprime[j] = true; for(int i = 2; i < maxn; i++) if(!isprime[i]) prime[cnt++] = i; return cnt; } int main() { int T,cnt,n; scanf("%d", &T); cnt = init(); for(int kase = 1; kase <= T; kase++) { scanf("%d", &n); LL sum = 1; int temp = n; for(int i = 0; i < cnt && prime[i] < temp; i++) { int ans = 0; while(n % prime[i] == 0) { n /= prime[i]; ans++; } sum *= (2*ans+1); } if(n > 1) sum *= 3; //比如当n等于2的时候 printf("Scenario #%d:\n%I64d\n\n", kase, (sum+1)/2); } return 0; }
HDU 1719 Friend
假设Fn=a*b+a+b,转化可得Fn+1 = (a+1)*(b+1),又因为a,b的初始值为1,2,因此对于每一个成立的数n,n+1能整除2或者3.注意要考虑n为0的情况。#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; int main() { int n; while(scanf("%d", &n) != EOF) { if(!n) { printf("NO!\n"); continue; } n++; while(n%2 == 0) n /= 2; while(n%3 == 0) n /= 3; if(n == 1) printf("YES!\n"); else printf("NO!\n"); } return 0; }
相关文章推荐
- pip install 出现报asciii码错误的解决
- Program4_S
- 供应链金融案例
- bzoj 4100 [Usaco2015 Open]Bessie Goes Moo
- 新浪微博技术架构问题解析
- 提高项目23-有序数组中插入数据(函数版)
- 嗯 想写个demo 苦于没数据
- HDU 2852 KiKi's K-Number (树状数组+二分)
- 图算法4之1005
- Windows+VS2013爆详细Caffe编译安装教程
- centOS 6.5采用python+nginx+uwsgi实现爬金十财经日历
- 设计模式总结
- C++语言实现螺旋队列
- ESN向MEID转换常见问题解答
- 2016年该如何去做SEO?
- IntelliJ IDEA 添加项目后编译显示包不存在的解决方案
- 作为基础开发人员必须掌握的linux常用命令
- 糗百的HTML更改后的python爬虫,2016,7,5 总计
- 关爱程序员
- Linux第三周