比赛2总结
T1
题意
给定一个整数序列a1,a2 , …,判断是否能将其分为奇数段(每段不为空0),每段具有奇数长度且开始和结束为奇数。
代码
include<bits/stdc++.h>
using namespace std;
int main()
{
int n,a[101],i,j,k,z;
cin>>n;
for(i=1;i<=n;i++)
cin>>a[i];
if(n%2==0||a[1]%2==0||a[n]%2==0)
//仅需判断总长度首尾是否为奇数
{
cout<<"NO";
return 0;
}
cout<<"YES";
}
T2
题意
输入整数序列a1,a2 , …,点坐标为(i,a[i]),是否有可能画出两条平行且非重叠的线,使每一个点都恰好位于其中一个点上,且每条线都穿过至少一个点。
代码
include<bits/stdc++.h>
using namespace std;
int n,pd=0;
long double a[1010];
void f(long double k,int lw)
{
int i,ks,pd2=0;
ks=lw-1;
if(ks==0) ks=3;
for(i=4;i<=n;i++)
{
if((a[i]-a[ks])/(i-ks)!=k&&(a[i]-a[lw])/(i-lw)!=k)
pd2=1;
}
if(pd2==0) pd=0;
}
int main()
{
long double k,cs1,cs2,cs3;
int i,m,j,pd2=0;
cin>>n;
for(i=1;i<=n;i++)
{
cin>>a[i];
}
cs1=a[2]-a[1];
cs2=a[3]-a[2];
cs3=(a[3]-a[1])/2;
//根据前三个点算出斜率的三种可能并一一实验
if(n==3&&cs1==cs2)
{
cout<<"No";
return 0;
}
if(cs1==cs2)
{
k=cs1;
pd=0;
pd2=0;
for(i=4;i<=n;i++)
{
if((a[i]-a[3])/(i-3)!=k)
{
pd2=1;
m=i;
break;
}
}
if(pd2==0)
pd=1;
else
for(i=m+1;i<=n;i++)
{
if((a[i]-a[3])/(i-3)!=k&&(a[i]-a[m])/(i-m)!=k)
{
pd=1;
break;
}
}
}
else
{
pd=1;
f(cs1,3);
f(cs2,1);
f(cs3,2);
}
if(pd==0) cout<<"Yes";
if(pd==1) cout<<"No";
}
T3
题意
合并字符串,先输入一个数表示成本,输出其中一个该成本的字符串。
合并价格:被合并字符串中的合并字母数。
例:a与aa合并要1*2=2。
代码
include<bits/stdc++.h>
using namespace std;
int main()
{
int sum,n,i,p,k=0;
cin>>n;
if(n==0)
{
cout<<"a";
return 0;
}
while(n!=0)
{
k++;
for(i=1;;i++)
{
if((i-1)*i/2>n)
{
p=i-1;
n-=(p-1)*p/2;
break;
}
}
for(i=1;i<=p;i++)
{
cout<<char(k+96);
}
}
}
T4
题意
输入n,输出边长为2的n次方的正方形字符方阵,由‘+’与‘*’构成。
其中+表示+1,表示*表示-1。
使相邻行与相邻列中中相邻数乘积之和为0;
样例:
Input
2
Output
++ * *
+* + *
+++ +
+* * +
代码
include<bits/stdc++.h>
using namespace std;
int n;
char a[513][513];
void fx(int x,int y,int n,int zf)
{
if(n==1)
{
if(zf==1)
{
a[x][y]=a[x+1][y]=a[x][y+1]='+';
a[x+1][y+1]='*';
}
if(zf==0)
{
a[x][y]=a[x+1][y]=a[x][y+1]='*';
a[x+1][y+1]='+';
}
}
else
{
fx(x,y,n-1,zf);
fx(x+(1 << n-1),y,n-1,zf);
fx(x,y+(1 << n-1),n-1,zf);
fx(x+(1 << n-1),y+(1 << n-1),n-1,1-zf);
}
}
int main()
{
int i,j;
cin>>n;
if(n==0)
{
cout<<"+";
return 0;
}
fx(1,1,n,1);
for(i=1;i<=(1 << n);i++)
{
for(j=1;j<=(1 << n);j++)
cout<<a[j][i];
cout<<endl;
}
}
//主要用分形的方法,其中*反一下输出
T5
题意
第一行输入n
第二行再输入n个整数a1,a2等
输入m,接下来m行每行输入两整数,p,q,列举p与q间的质数,并判断是否能被a1,a2等整除,计算总个数并输出。
数据范围:1 ≤ n ≤ 10的六次方,2 ≤ ai ≤ 10的七次方,1 ≤ m ≤ 50000,2 ≤ p≤ q ≤ 2·10的九次方。
代码
#include<bits/stdc++.h>
using namespace std;
const int N=10000005;
long long a,b[N],c[N],sum[N];
int main()
{
long long n,m,k,i,j,p,q;
ios::sync_with_stdio(false);//加速
cin>>n;
for(i=1;i<=n;i++)
{
cin>>a;
c[a]++;
} //数组c【i】表示i的个数
for(i=2;i<N;i++)
{
if(!b[i])
{
for(j=i;j<N;j+=i)//筛选法求质数,排除掉质数的倍数
{
b[j]=1;
if(c[j])
{
sum[i]+=c[j];//其中j为i的倍数,故sum可以记录每一个质数的倍数数量
}
}
}
}
for(i=1;i<=N;i++)//因为最大一直到N,故前缀和要求到N
{
sum[i]+=sum[i-1];//前缀和,sum【i】为1到i的个数和
}
cin>>m;
for(i=1;i<=m;i++)
{
cin>>p>>q;
if (p>N)
{
p=N-1;
}
if (q>N)
{
q=N;//若超过了范围则直接变为N,因为质数不会超过N,故超过N的数当作N处理
}
cout<<sum[q]-sum[p-1]<<endl;
}
}
总结
3:难度不大,但未看懂。
4:问题在于漏条件,未想到分形。
5:超时,应优化算法,用前缀求和,并用筛法求质数,详见代码。