好久没写博客来。
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]就可以了,也不难。
JAVA版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;
}
总的来说,这套题比较简单,但是做的不是很理想。