BestCoder Round #54 (div.2)
2015-09-06 01:13
411 查看
好久没写博客来。
1001 排序题
首先就是字符串处理,小心空格就可以了 用整行读入。水题。用了8分钟搞定
1002 给定n个数,这n个数相乘有一个乘积,现在要你找出这个乘积的最小因子,这个因子约数最少要有3个,约数包括本身。
虽然我们不能算出这个乘积,但是我们可以对每个数进行分解质因数。然后取最小的两个质因数出来相乘即为满足题目要求的最小因子。
首先,因为最小的两个质因数相乘的结果可以保证,它约数最少是3个,而且它必然是最小因子(所有满足约数个数大于等于3的最小因子)。
为了方便起见,我们可以把分解出来的质因数统一放到一个动态数组里,分解完所有数之后,只需排序那个存放质因数的数组,取最小的两个因子即可。如果动态数组元素个数小于2,那显然不存在解。。。
1003
1003 是题意理解得不够透彻,而导致程序漏了一种情况,就是n个数全为0的时候是等比数列,而我们一开始认为,数列长度大于2的时候一旦有0就一定不是等比数列,事实上只有当数列长度大于等于2,数列存在0且不全为0才不是等比数列。所以,程序要先处理好0的问题,然后扫一遍是否每个数a[i]都满足,a[i-1]*a[i+1]=a[i]*a[i]就可以了,也不难。
J***A版AC代码来一发
当然少不了C++版的
1004 欧拉函数模板题
如果直接叫我算法欧拉函数我是会的,如果变下形,隐藏得很深,那我就不会了。。。
打表的欧拉函数来一发 复杂度O(n)
基于分解质因数的来一发
这两个的区别在于,打表法快是快,但是数组最多开到1000000,而基于分解质因数的可以求10^12以内的所有数的欧拉函数。
总的来说,这套题比较简单,但是做的不是很理想。
1001 排序题
首先就是字符串处理,小心空格就可以了 用整行读入。水题。用了8分钟搞定
#include<cstdio> #include<cstring> #include<cmath> #include<cstdlib> #include<ctime> #include<iostream> #include<algorithm> #include<sstream> #include<fstream> #include<vector> #include<map> #include<stack> #include<list> #include<set> #include<queue> #define LL long long #define lson l,m,rt<<1 #define rson m+1,r,rt<<1 | 1 /* 正反循环的宏定义 */ #define ffr(i,x,y) for(int i=(x),_en=(y);i<=_en;i++) #define rff(i,x,y) for(int i=(x),_en=(y);i>=_en;i--) #define clr(f,z) memset(f,z,sizeof(f)) using namespace std; const int maxn=100005,inf=1<<29; int dir[][2]={ {0,1},{-1,0},{0,-1},{1,0},{-1,1},{-1,-1},{1,-1},{1,1}};//常用方向数组 int n,m,t;//常用全局变量 struct node { string s; int num; }a[maxn];//常用结构体 vector<int>G[maxn];//常用邻接表 bool cmp(node a,node b)//常用排序规则 { return a.num>b.num; } /* 函数重载,可根据参数类型,自动选择输入 */ bool sf(int &x) { return scanf("%d",&x)==1;} bool sf(char *x){return scanf("%s",x)==1;} bool sf(double &x){return scanf("%lf",&x)==1;} bool sf(LL &x) { return scanf("%I64d",&x)==1;} void pf(int x,int op) { op?printf("%d\n",x):printf("%d ",x);//op==0打印数字加空格,op==1打印数字加换行 } int get_rand(int n) { return (int)((double)rand() / RAND_MAX * n) ; } int main() { //freopen("in.txt","r",stdin); //freopen("out.txt","w",stdout); //srand(time(NULL)); sf(t); while(t--) { sf(n); string s; getline(cin,s); ffr(i,0,n-1) { getline(cin,s); int len=s.size(); a[i].s=s.substr(0,len-5);//取出字符串部分 a[i].num=(s[len-4]-'0')*1000+(s[len-3]-'0')*100+(s[len-2]-'0')*10+(s[len-1]-'0')*1;//取出年份 //cout<<a[i].s<<" "<<a[i].num<<endl; } sort(a,a+n,cmp); ffr(i,0,n-1) cout<<a[i].s<<endl; } return 0; }
1002 给定n个数,这n个数相乘有一个乘积,现在要你找出这个乘积的最小因子,这个因子约数最少要有3个,约数包括本身。
虽然我们不能算出这个乘积,但是我们可以对每个数进行分解质因数。然后取最小的两个质因数出来相乘即为满足题目要求的最小因子。
首先,因为最小的两个质因数相乘的结果可以保证,它约数最少是3个,而且它必然是最小因子(所有满足约数个数大于等于3的最小因子)。
为了方便起见,我们可以把分解出来的质因数统一放到一个动态数组里,分解完所有数之后,只需排序那个存放质因数的数组,取最小的两个因子即可。如果动态数组元素个数小于2,那显然不存在解。。。
#include<cstdio> #include<algorithm> #include<cmath> #include<cstring> #include<vector> #include<map> #include<iostream> #define LL long long using namespace std; const int L=100005,inf=1<<30,maxn=1005; int prime[L],np=0; bool is[L]; vector<int>ans; void getPrime()//筛法求素数 { fill(is,is+L,1); is[1]=0; for(int i=2;i<L;i++) if(is[i]) { prime[++np]=i; for(int j=2*i;j<L;j+=i) is[j]=0; } // for(int i=1;i<=np;i++) //cout<<prime[i]<<" "; } bool is_prime(int n)//素数判定 { for(int i=1;prime[i]*prime[i]<=n;i++) if(n%prime[i]==0) return 0; return 1; } vector<int> divisor(int n)//求约数 { vector<int>ans; for(int i=1;i*i<=n;i++) if(n%i==0) { ans.push_back(i); if(i*i!=n) ans.push_back(n/i); } return ans; } void factor(int n)//因式分解 { //map<int,int>ans; for(int i=1;prime[i]*prime[i]<=n;i++) { while(n%prime[i]==0) { //ans[prime[i]]++; ans.push_back(prime[i]); n/=prime[i]; } } if(n!=1) ans.push_back(n); //return ans; } int main() { getPrime(); int n,t; cin>>t; while(t--) { ans.clear(); cin>>n; for(int i=0;i<n;i++) { int x; cin>>x; factor(x);//分解质因数 } if(ans.size()<2) puts("-1"); else { sort(ans.begin(),ans.end()); LL res=(LL)ans[0]*ans[1];//取最小的两个因子 printf("%I64d\n",res); } } return 0; }
1003
1003 是题意理解得不够透彻,而导致程序漏了一种情况,就是n个数全为0的时候是等比数列,而我们一开始认为,数列长度大于2的时候一旦有0就一定不是等比数列,事实上只有当数列长度大于等于2,数列存在0且不全为0才不是等比数列。所以,程序要先处理好0的问题,然后扫一遍是否每个数a[i]都满足,a[i-1]*a[i+1]=a[i]*a[i]就可以了,也不难。
J***A版AC代码来一发
import java.util.*; import java.math.*; import java.io.*; public class Main { static Scanner cin=new Scanner(System.in); static public void main(String args[]){ BigInteger a,b,c[]=new BigInteger[105],z=BigInteger.ZERO; int t=cin.nextInt(),n; while(t>0) { t--; n=cin.nextInt(); for(int i=1;i<=n;i++) c[i]=cin.nextBigInteger(); boolean f=true,all=true,only=false; for(int i=1;i<=n;i++) if(c[i].equals(z)) only=true; else all=false; if(all) { System.out.println("Yes"); continue; } if(only) { System.out.println("No"); continue; } for(int i=2;i<=n-1;i++) if(c[i-1].multiply(c[i+1]).equals(c[i].multiply(c[i]))==false) f=false; if(f==false) System.out.println("No"); else System.out.println("Yes"); } } }
当然少不了C++版的
#include <iostream> #include <cstdio> #include <algorithm> #include <cstring> #include <cmath> #include <map> #include <queue> #include <set> #include <vector> using namespace std; #define L(x) (1 << (x)) const double PI = acos(-1.0); const int Maxn = 10015; double ax[Maxn], ay[Maxn], bx[Maxn], by[Maxn]; char sa[Maxn/2],sb[Maxn/2]; int sum[Maxn]; int x1[Maxn],x2[Maxn]; int revv(int x, int bits) { int ret = 0; for (int i = 0; i < bits; i++) { ret <<= 1; ret |= x & 1; x >>= 1; } return ret; } void fft(double * a, double * b, int n, bool rev) { int bits = 0; while (1 << bits < n) ++bits; for (int i = 0; i < n; i++) { int j = revv(i, bits); if (i < j) swap(a[i], a[j]), swap(b[i], b[j]); } for (int len = 2; len <= n; len <<= 1) { int half = len >> 1; double wmx = cos(2 * PI / len), wmy = sin(2 * PI / len); if (rev) wmy = -wmy; for (int i = 0; i < n; i += len) { double wx = 1, wy = 0; for (int j = 0; j < half; j++) { double cx = a[i + j], cy = b[i + j]; double dx = a[i + j + half], dy = b[i + j + half]; double ex = dx * wx - dy * wy, ey = dx * wy + dy * wx; a[i + j] = cx + ex, b[i + j] = cy + ey; a[i + j + half] = cx - ex, b[i + j + half] = cy - ey; double wnx = wx * wmx - wy * wmy, wny = wx * wmy + wy * wmx; wx = wnx, wy = wny; } } } if (rev) { for (int i = 0; i < n; i++) a[i] /= n, b[i] /= n; } } int solve(int a[],int na,int b[],int nb,int ans[]) { int len = max(na, nb), ln; for(ln=0; L(ln)<len; ++ln); len=L(++ln); for (int i = 0; i < len ; ++i) { if (i >= na) ax[i] = 0, ay[i] =0; else ax[i] = a[i], ay[i] = 0; } fft(ax, ay, len, 0); for (int i = 0; i < len; ++i) { if (i >= nb) bx[i] = 0, by[i] = 0; else bx[i] = b[i], by[i] = 0; } fft(bx, by, len, 0); for (int i = 0; i < len; ++i) { double cx = ax[i] * bx[i] - ay[i] * by[i]; double cy = ax[i] * by[i] + ay[i] * bx[i]; ax[i] = cx, ay[i] = cy; } fft(ax, ay, len, 1); for (int i = 0; i < len; ++i) ans[i] = (int)(ax[i] + 0.5); return len; } string mul(string sa,string sb) { int l1,l2,l; int i; string ans; memset(sum, 0, sizeof(sum)); l1 = sa.size(); l2 = sb.size(); for(i = 0; i < l1; i++) x1[i] = sa[l1 - i - 1]-'0'; for(i = 0; i < l2; i++) x2[i] = sb[l2-i-1]-'0'; l = solve(x1, l1, x2, l2, sum); for(i = 0; i<l || sum[i] >= 10; i++) // 进位 { sum[i + 1] += sum[i] / 10; sum[i] %= 10; } l = i; while(sum[l] <= 0 && l>0) l--; // 检索最高位 for(i = l; i >= 0; i--) ans+=sum[i] + '0'; // 倒序输出 return ans; } string ssa[Maxn]; bool zero(string s) { int num=0; for(int i=0;i<s.size();i++) { num=num*10+s[i]-'0'; if(num) return 0; } return 1; } int main() { cin.sync_with_stdio(false); string a,b; int t,n; cin>>t; while(t--) { cin>>n; for(int i=1;i<=n;i++) cin>>ssa[i]; bool f=1,all=true,only=false; for(int i=1;i<=n;i++) if(zero(ssa[i])) only=true; else all=false; if(all) { puts("Yes"); continue; } if(only) { puts("No"); continue; } for(int i=2;i<=n-1;i++) if(mul(ssa[i-1],ssa[i+1])!=mul(ssa[i],ssa[i])) { f=0; break; } if(f) puts("Yes"); else puts("No"); } return 0; }
1004 欧拉函数模板题
如果直接叫我算法欧拉函数我是会的,如果变下形,隐藏得很深,那我就不会了。。。
打表的欧拉函数来一发 复杂度O(n)
#include<iostream> using namespace std; const int maxn=1000005; int phi[maxn]; int main() { int n,t; for(int i=0;i<maxn;i++) phi[i]=i; for(int i=2;i<maxn;i+=2) phi[i]/=2; for(int i=3;i<maxn;i++) if(phi[i]==i) { for(int j=i;j<maxn;j+=i) phi[j]=phi[j]/i*(i-1); } cin>>t; while(t--) { cin>>n; cout<<phi[n+1]<<endl; } return 0; }
基于分解质因数的来一发
这两个的区别在于,打表法快是快,但是数组最多开到1000000,而基于分解质因数的可以求10^12以内的所有数的欧拉函数。
#include<cstdio> #include<cstring> #include<iostream> using namespace std; int f(int n) { int ans = n; for (int i = 2 ; i * i <= n ; 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 T; int n; cin>>T; while (T--) { cin>>n; n++; int ans = f(n); cout<<ans<<endl; } return 0; }
总的来说,这套题比较简单,但是做的不是很理想。
相关文章推荐
- c语言预编译以及static,extern的使用
- 【Unity资讯】Linux平台下的Unity编辑器实验版发布
- 关于Json的一些东西
- Unity Game Programming AI(3)路径跟随
- BestCoder Round #54 (div.2) HDOJ5428 The Factor(脑洞)
- 前端资源版本控制的那些事儿
- 阳光充沛的一天
- .Net加密与解密
- 电视挂墙
- ssh比较全的一个网站
- 笔试题:判断一个树是不是平衡二叉树
- poj2728 Desert King(最优比率生成树)
- http-url那些事
- Android控件拖动的实现
- java的十个调试技巧
- HDU 4445 数学-抛物运动
- 阳江游记
- 寻找质数之和
- 91 POST JSON 多值参数 获得mineType
- uva 11093