啊假期结束了,可以休息一阵子了
UVA-10892 分解&选择
#include<iostream> #include<cstdio> #include<cstring> using namespace std; typedef long long ll; bool isp[1000005]; int p[80005]; int f[100005]; int m,co; void pri() { co = 0; for (int i = 2; i < 1000005; i++)isp[i] = 1; for (int i = 2; i < 1000005; i++) { if (isp[i])p[co++] = i; for (int j = 0; j < co&&i*p[j] < 1000005; j++)isp[i*p[j]] = 0; } } void d(ll n) { m = 0; for (int i=0; i<co; i++) { if (n%p[i])continue; else{ while (n%p[i] == 0) { f[m]++; n /= p[i]; } m++; } } } int main() { pri(); ll n; while (cin >> n && n) { memset(f, 0, sizeof(f)); d(n); ll ans = 1; for (int i = 0; i < m; i++) ans *= f[i] * 2 + 1; ans = (ans + 1) / 2; cout << n << " " << ans << endl; } return 0; }
把给出的数分解质因数,然后考虑分别分配给两个数,这样可得最小公倍数为n。
我没有什么别的想法,我觉得题解说的有道理。
UVA-11752 我觉得头大
找出所有2^64以下的均能由两个不同的数的次方构成的数。
一个是从头到尾枚举底数枚举次数来一遍。一开始没想到怎么解决从小到大的问题,后来发现重复的问题也解决不了。题解告诉我这不就是set了嘛。
#include<iostream> #include<cstdio> #include<algorithm> #include<set> #include<cmath> using namespace std; typedef unsigned long long ull; bool np[100]; int p[100]; void cpl() { int co = 0; for (int i = 2; i < 65; i++) { if (!np[i])p[co++] = i; for (int j = 0; j < co&&i*p[j] < 65; j++) { np[i*p[j]] = 1; } } } int main() { set<ull>ans; cpl(); ans.insert(1); int m = 1 << 16; ull t = -1; for (int i = 2; i <= m; i++) { ull a = 1; for (int j = 1; j < 64; j++) { a *= i; if (np[j])ans.insert(a); if (a > t / i)break; } } set<ull>::iterator i; for (i = ans.begin(); i != ans.end(); i++)cout << *i << endl; return 0; }
另一个是换底公式把当前底数的最大次数算出来再枚举。这个方式卡了自己好久,最后发现是因为合数表(?)打出来的时候并不是按照从小到大的顺序,直接导致在后面循环乘的时候疯狂乘爆(其实这个也可以通过三目运算符来解决:(a[j]-a[j-1]==1)?*i:*i*i,我就是不想写三目运算符哼╭(╯^╰)╮)
#include<iostream> #include<cstdio> #include<algorithm> #include<set> #include<cmath> using namespace std; typedef unsigned long long ull; bool np[100]; int a[100],p[100]; void cpl() { int co = 0,cc=0; for (int i = 2; i < 65; i++) { if (!np[i])p[co++] = i; for (int j = 0; j < co&&i*p[j] < 65; j++) np[i*p[j]] = 1; } for (int i = 2; i < 65; i++) if (np[i])a[cc++] = i; //sort(a, a + cc); } int main() { set<ull>ans; cpl(); ans.insert(1); int ma = 1 << 16; for (ull i = 2; i <= ma; i++) { int m = ceil(64 * log(2) / log(i)) - 1; ull an = i * i * i * i; if(i!=ma)ans.insert(an); for (int j = 1; a[j] <= m; j++) { for (int k = 0; k < a[j] - a[j - 1]; k++)an *= i; ans.insert(an); } } set<ull>::iterator i; for (i = ans.begin(); i != ans.end(); i++)cout << *i << endl; return 0; }
对了,重新排序的时候扫一遍应该会比sort快一丢丢。
UVA-10780 我觉得头极大
一开始自己推了个规律结果发现没考虑到6 4这样的状况,也就是有因子没本身的时候,好,那我就把因子分解出来。
然后就有一些奇奇怪怪的错误,然后把ans从0x3f3f3f改到0x3f3f3f3f,又改min,又改输出条件……反正最后就这样了
#include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; int t, n, m; int fa[10050]; void got(int n) { for (int i = 2; i*i <= n; i++) { while (n%i == 0) { fa[i]++; n /= i; } } fa[n]++; } int main() { cin >> t; for (int i = 1; i <= t; i++) { memset(fa, 0, sizeof(fa)); cin >> m >> n; int ans = 0x3f3f3f3f; for (int j = 2; j <= n; j++) { got(j); } int co; for (int j = 2; j <= m; j++) { co = 0; while (m%j == 0) { co++; m /= j; } if (co)ans = min(ans, fa[j] / co); } //ans = min(ans, fa[m]); if (ans)printf("Case %d: %d ", i, ans); else printf("Case %d: Impossible to divide ", i); } return 0; }
整个假期全是数学题,魔鬼!!!(╯‵□′)╯︵┻━┻