https://cn.vjudge.net/contest/183263#overview
[toc]
A - Odds and Ends
题意
- 一组n个数,分割成连续的子串,使子串数量为奇数,每个子串长度为奇数,头尾都为奇数。
思路
- 如果n为偶数,无法操作;如果n为奇数,不需分割,只需第一个数和最后一个数位奇数。
题解
#include<cstdio>
int main()
{
int n,a[101];
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",a+i);
if(!(a[1]&1)||!(a[n]&1)||!(n&1)) printf("No");
else printf("Yes");
}
B - Tell Your World
题意
- 平面上有一些点,用两条直线将他们全部串起来。
思路
- 固定第一个点,枚举其他点与它相连成为第一条直线,其他点在这条或与它平行的同一条直线上。
题解
#include<cstdio>
const int MAXN=1010; //当把MAXN赋为1000时出现了TLE
int n,y[MAXN];
double getk(int b)
{
return (double)(y[b]-y[1])/(b-1);
}
double getb(double k)
{
return (double)y[1]-k;
}
void input()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",y+i);
}
int trys(int m)
{
double k=getk(m);
double b1=getb(k),b2=b1;
// printf("\n%llf %llf\n",k,b1);
bool v[MAXN]={0};
for(int i=1;i<=n;i++)
if(k*i+b1==y[i]) v[i]=1;
for(int i=1;i<=n;i++)
{
if(v[i]==0)
{
if(b2==b1) b2=y[i]-i*k;
else{
if(k*i+b2!=y[i]) return 0;
}
}
}
if(b2==b1) return -1;
return 1;
}
int main()
{
input();
for(int i=2;i<=n;i++)
{
int t=trys(i);
if(t==-1){
printf("No");
return 0;
}
if(t==1){
printf("Yes");
return 0;
}
}
int tmp=y[1];
for(int i=2;i<=n;i++) y[i-1]=y[i];
y[n]=tmp;
int t=trys(2);
if(t==1){
printf("Yes");
return 0;
}
printf("No");
}
C - From Y to Y
题意
- 对于一个字符串,把每个字符看成一个长度为1的串,合并两个串的代价是两串中每种相同字符的乘积的总合.输入一个数,求一个符合最小合成总合是这个数的串.
思路
- 对于单字符种类的串,合成代价是n*(n-1)/2;把一个串中相同字符各自合并,在相互合并是最优方法.
题解
#include<cstdio>
#include<cmath>
const int N=100010;
int f(int x)
{
return x*(x-1)/2;
}
float def(int x)
{
return sqrt(x*2+0.25)+0.5;
}
int main()
{
char c='a';
int k;
scanf("%d",&k);
if(k==0) printf("shit");
while(k>0)
{
int d=def(k);
for(int i=1;i<=d;i++) printf("%c",c);
c++;
k-=f(d);
}
}
D - Harmony Analysis
题意
- 输入k,输出一个(1”<<”k)*(1”<<”k) 的矩阵,内容为”*”和“+”,使任意两行对应格的字符 相同和不同的数量相同。
思路
- 二分,将矩阵分成四个相等的矩阵,右下角的与其他的相反.
题解
#include<cstdio>
const int MAXN=1024;
bool b[MAXN][MAXN];
void prework()
{
for(int i=0;i<=8;i++)
{
for(int j=0;j<(1<<i);j++)
for(int k=0;k<(1<<i);k++)
{
b[j+(1<<i)][k]=b[j][k];
b[j][k+(1<<i)]=b[j][k];
b[j+(1<<i)][k+(1<<i)]=!b[j][k];
}
}
}
int main()
{
prework();
int k;
scanf("%d",&k);
for(int i=0;i<1<<k;i++)
{
for(int j=0;j<1<<k;j++)
b[i][j] ? printf("+") : printf("*");
printf("\n");
}
}
E - Bear and Prime Numbers
题意
- 给出一些数,给出一个区间,求其中的质数能被列出的数整除的次数总合.
思路
- 筛选法求质数被整除次数,前缀和优化
题解
#include <stdio.h>
#include <string.h>
const int N = 10000005;
int n, m, v[N], g[N], s[N];
void init() {
memset(v, 0, sizeof(v));
memset(g, 0, sizeof(g));
memset(s, 0, sizeof(s));
int a;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%d", &a);
g[a]++;
}
for (int i = 2; i < N; i++) {
if (v[i]) continue;
for (int j = i; j < N; j += i) {
if (g[j]) s[i] += g[j];
v[j] = 1;
}
}
for (int i = 1; i < N; i++) s[i] += s[i-1];
}
void solve() {
int a, b;
scanf("%d", &m);
for (int i = 0; i < m; i++) {
scanf("%d%d", &a, &b);
if (a >= N) a = N;
if (b >= N) b = N - 1;
printf("%d\n", s[b] - s[a-1]);
}
}
int main() {
init();
solve();
return 0;
}