第一题
A. 暑假作业题 2014新生暑假个人排位赛07
题目描述
亲爱的小朋友们,暑假过了之后,你们要二年级啦!现在老师要检测一下你们一年级学习的读数,大家准备好自己的程序了吗?来读数吧!
输入格式
input
输入第一行包括一个整数t,t<=10^5,接下来t行每行有一个整数Ai,Ai<10^17
输出格式
output
输出每个数字的中文读法,每组数据以回车结束。为了简单起见,用阿拉伯数字0-9代替汉字零到九,用S代替十,B代替百,Q代替千,W代替万,E代替亿
输入样例
4
10
1101000
21000
1010010000001000
输出样例
1S
1B1SW1Q
2W1Q
1Q01SW01BE1Q
hint
10要读作一十
另外还有注意0的处理
机房电脑不识别%lld,要改成%I64d
注意是大写的i,I64d,不是l64d
读入可以用字符串,也可以用long long
下面有两种代码
用字符串读取
#include <iostream>
#include <cstdio>
#include <string.h>
#include <vector>
#include <cmath>
#include <algorithm>
using namespace std;
int help, help1, help2;
int tapp;
void cal(int tag, int bt)
{
if (bt>=1e4)
{
help = bt/1e4;
cal(tag, help);
printf("W");
cal(4, bt%10000);
}
else if (bt>=1e3)
{
printf("%dQ", bt/1000);
help = bt%1000;
cal(3, help);
}
else if (bt>=1e2)
{
if ((tag == 4)||(tag==5))
printf("0");
printf("%dB", bt/100);
help = bt%100;
cal(2, help);
}
else if (bt>=10)
{
if ((tag == 3)||(tag==4)||(tag==5))
printf("0");
printf("%dS", bt/10);
help = bt%10;
cal(1, help);
}
else if (bt>0)
{
if ((tag == 3)||(tag == 2)||(tag == 4)||(tag==5))
printf("0");
printf("%d", bt);
}
}
int main()
{
int n;
scanf("%d", &n);
for (int i=0; i<n; i++)
{
char b[20], c[20];
scanf("%s", b);
if (strlen(b)>8)
{
int len = strlen(b)-9;
for (int j=0; j<=len; j++)
c[j] = b[j];
c[len+1] = 0;
help1 = atoi(c);
if (help1)//这里是为了预防出现前导0的情况
{
cal(0, help1);
printf("E");
}
for (int j=len+1; j<=len+8; j++)
c[j-len-1] = b[j];
c[8] = 0;
help2 = atoi(c);
if (help2)
cal(5, help2);
else if ((!help1)&&(!help2))
printf("0");
}
else
{
help1 = atoi(b);
if (help1)
cal(0, help1);
else
printf("0");
}
printf("\n");
}
return 0;
}
用long long 读取,主函数里的处理会变得简单很多
#include <iostream>
#include <cstdio>
#include <string.h>
#include <vector>
#include <cmath>
#include <algorithm>
using namespace std;
long long b;
int help, help1, help2;
void cal(int tag, int bt)
{
if (bt>=1e4)
{
help = bt/1e4;
cal(tag, help);
printf("W");
cal(4, bt%10000);
}
else if (bt>=1e3)
{
printf("%dQ", bt/1000);
help = bt%1000;
cal(3, help);
}
else if (bt>=1e2)
{
if ((tag == 4)||(tag==5))
printf("0");
printf("%dB", bt/100);
help = bt%100;
cal(2, help);
}
else if (bt>=10)
{
if ((tag == 3)||(tag==4)||(tag==5))
printf("0");
printf("%dS", bt/10);
help = bt%10;
cal(1, help);
}
else if (bt>0)
{
if ((tag == 3)||(tag == 2)||(tag == 4)||(tag==5))
printf("0");
printf("%d", bt);
}
}
int main()
{
int n;
scanf("%d", &n);
for (int i=0; i<n; i++)
{
scanf("%lld", &b);
if (b==0)
printf("0");
else if (b>=100000000)
{
cal(0, b/100000000);
printf("E");
cal(5, b%100000000);
}
else
cal(0, b);
printf("\n");
}
return 0;
}
第二题
443. 最长数链
题目描述
现有正整数集A={i|i>0&&i<=n},求A的子集合B,使得对于任意x属于B,y属于B,x整除y或y整除x。优先考虑所含元素多的子集合,然后优先考虑所含元素和大的子集合,然后优先考虑字典序小的子集合。
输入格式
每组数据包含一行一个整数n(n<1e5).输入以EOF结束。
输出格式
每组数据输出一行,从小到大输出所求集合,注意行尾不要有空格。
输入样例
6
100
输出样例
1 3 6
1 3 6 12 24 48 96
而前面
只有可能是1 2 4 8,或者1 3 6 12,因为1 4 8 16里面就可以加个2了
#include <iostream>
#include <cstdio>
#include <string.h>
#include <vector>
#include <cmath>
#include <algorithm>
using namespace std;
int main()
{
int n;
while (~scanf("%d", &n))
{
int ans = -1;
int t = n;
while (t>0)
{
ans++;
t = t>>1;
}
printf("1");
int tl;
if (((1<<(ans-1))*3) <= n) // 2 的(ans-1)次方乘以3小于等于n
tl = 3;
else
tl = 2;
for (int i=0; i<=ans-1; i++)
{
printf(" %d", tl);
tl *= 2;
}
cout << endl;
}
return 0;
}
第三题
C. 三角形的传说 2014新生暑假个人排位赛07
题目描述
有一个传说,对给定正整数 m 和 q,总有一个边长为 a,b,c 的三角形,是满足 a % m + b % m = c % m = q 的条件的三角形中周长最小的。
Mays 对此深信不疑,她打算和你一起探讨这个问题。她出了一些数据,请你帮忙求最小周长,如果找不到这样一个三角形,也请你告诉她这个惨痛的事实。
输入格式
给一个组数 T。接下来 T 组,每组两个数字 m 和 q ,(1 <= m <= 10^5 , 0 <= q < m)。
输出格式
输出当前组数和最小周长,格式见样例。若不存在满足的三角形,请把最小周长的数字替换成"Poor Mays!".
输入样例
2
3 2
3 2
输出样例
Case 1: 7
Case 2: 7
#include <iostream>
#include <cstdio>
#include <string.h>
#include <vector>
#include <cmath>
#include <algorithm>
using namespace std;
int main()
{
int t;
scanf("%d", &t);
for (int i=1; i<=t; i++)
{
int m, q;
scanf("%d %d", &m, &q);
if (q==0)
printf("Case %d: %d\n", i, 3*m);
else if (2*q > m)
printf("Case %d: %d\n", i, 2*q+m);
else if (q==1)
printf("Case %d: %d\n", i, 3*m+2*q);
else
printf("Case %d: %d\n", i, 2*m+2*q);
}
return 0;
}
第四题
这题有两种方法,规范的话用spfa,其实我真没弄明白这个和迪杰斯特拉到底什么区别
另一种直接来回松弛(可能是题目并不复杂吧)
来回松弛法
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
using namespace std;
int a[10005]; // 存起点到该传送门最短距离
int b[10005]; // 该传送门到终点最短距离
int main()
{
int n, m;
scanf("%d %d", &n, &m);
while (n&&m)
{
int temp;
for (int i=1; i<=n; i++)
{
scanf("%d", &temp);
a[i] = i+temp-2;
b[i] = n+m-temp-i;
}
for (int i=2; i<=n; i++)// 顺着松弛一遍
{
a[i] = min(a[i], a[i-1]+1);
b[i] = min(b[i], b[i-1]+1);
}
for (int i=n-1; i>0; i--)// 反着松弛一遍
{
a[i] = min(a[i], a[i+1]+1);
b[i] = min(b[i], b[i+1]+1);
}
int sum = m+n-2; // 这个是最大体力消耗了了,不管过不过传送门
for (int i=1; i<=n; i++)
{
sum = min(sum, a[i]+b[i]); // a[i]+b[i]是假如过这个传送门最少体力消耗
}
printf("%d\n", sum);
scanf("%d %d", &n, &m);
}
return 0;
}
spfa + 手写链表 hullabaloo的代码
#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
#include<cstring>
#define SIZE_X 10010
#define INF 100000000
using namespace std;
int a[SIZE_X];
struct pre
{
int v,next,cost;
}pic[SIZE_X*4];
int e,head[SIZE_X*4];
bool vis[SIZE_X];
int d[SIZE_X];
void init()
{
e=0;
memset(head,-1,sizeof(head));
}
void savepic(int x,int y,int z)
{
pic[e].v=y;
pic[e].cost=z;
pic[e].next=head[x];
head[x]=e++;
}
int n,m;
int spfa(int st,int ed)
{
for(int i=0;i<=n+1;i++)
{
d[i]=INF;
vis[i]=0;
}
queue<int>que;
d[st]=0;
while(!que.empty())que.pop();
que.push(st);
while(!que.empty())
{
int v=que.front();
que.pop();
for(int i=head[v];i!=-1;i=pic[i].next)
{
int u=pic[i].v,w=pic[i].cost;
if(d[u]>d[v]+w)
{
d[u]=d[v]+w;
if(!vis[u]){que.push(u);vis[u]=1;}
}
}
vis[v]=0;
}
return d[ed];
}
int main()
{
while(~scanf("%d %d",&n,&m))
{
if(n==0&&m==0)
break;
init();
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
savepic(0,i,((m-a[i])+(n-i)));
savepic(i,n+1,((a[i]-1)+(i-1)));
if(i!=1)
savepic(i,i-1,1);
if(i!=n)
savepic(i,i+1,1);
}
printf("%d\n",spfa(0,n+1));
}
}
第五题 正在研究中。。。。