A.棋盘村
Time Limit: 1000 MS Memory Limit: 32768 K
Total Submit: 868 (212 users) Total Accepted: 122 (116 users) Special Judge: No
Description
一名骑着马的强盗闯进了原本平静祥和的棋盘村,为了通知村里的士兵来打败强盗,你必须要通知位于棋盘村最下方的兵营。棋盘村的地形就像是一张棋盘,你所在的位置为A点(0,0),兵营位于棋盘村的右下角B点(n,m)。你每次只能走一步,可以选择向下走,也可以选择向右走。但是强盗所在的位置和强盗的马一次所能跳到的位置是不可以走过去的(强盗的马的移动方法与象棋中的马相同)。请计算出从A点能够走到B点的所有路径条数。
Input
首先输入一个整数t,代表有t组测试数据。
每组测试数据为四个整数,即B点的坐标(n,m)和强盗的坐标(x,y)。
1 < n,m < 20.
Output
输出一个整数即路径的条数。
Sample Input
2
6 6 3 2
8 8 3 5
Sample Output
17
1393
递推,直接上代码。
#include
#include
#include
#define LL long long
using namespace std;
const int dx[]={1,1,2,2,-1,-1,-2,-2};
const int dy[]={2,-2,1,-1,2,-2,1,-1};
LL f[21][21];
bool g[21][21];
int main(){
int T,n,m,x,y;
cin>>T;
while(T--){
memset(f,0,sizeof(f));
memset(g,0,sizeof(g));
scanf("%d%d%d%d",&n,&m,&x,&y);
g[x][y]=1;
for(int i=0;i<=7;i++){
if(x+dx[i]<0||x+dx[i]>n) continue;
if(y+dy[i]<0||y+dy[i]>m) continue;
g[x+dx[i]][y+dy[i]]=1;
}
f[0][0]=1;
for(int i=0;i<=n;i++)
for(int j=0;j<=m;j++){
if(i==0&&j==0) continue;
if(i==0) f[i][j]=f[i][j-1];
if(j==0) f[i][j]=f[i-1][j];
if(i&&j) f[i][j]=f[i-1][j]+f[i][j-1];
if(g[i][j]) f[i][j]=0;
}
cout<return 0;
}
D.陈月亮的数学题
Time Limit: 2000 MS Memory Limit: 32768 K
Total Submit: 1341 (309 users) Total Accepted: 6 (6 users) Special Judge: No
Description
陈月亮从小就热爱数学,这天老师讲到任何一个正整数N,我们可以很容易的找出N的所有因子,N1,N2,N3...,Nk,称N一共有k个因子(包含1和N本身)。
求出k的值这个问题对于陈月亮来说实在是太简单了,于是她想要求出N所有因子的因子个数(如N1可能包含n1个因子(包含1和N1本身),N2可能包含n2个因子,...,Nk可能包含nk个因子),然后计算出S的值:
Input
第一行为一个整数T(T <= 10000),代表测试数据的组数。
接下来T行每行一个正整数N(N < 2 ^ 31)。
Output
对于每组测试数据,输出S的值。
Sample Input
2
6
9
Sample Output
81
36
这题以前做过!这题以前做过!这题以前做过!
然而考试的时候没看!!!
以后不能老是看榜做题了。
然后求
于是,打个素数表,然后分解质因数就好了。
蓝瘦,香菇。
#include
#include
using namespace std;
int prime[65536];
int s[100000],ans;
bool isprime(int x){
for(int i=2;i*i<=x;i++)
if(x%i==0) return 0;
return 1;
}
void printprime(){
for(int i=2;i<=65536*2;i++){
if(isprime(i)){
prime[++prime[0]]=i;
}
}
}
int main(){
printprime();
int a,b,cnt,top,T;
cnt=0;
scanf("%d",&T);
while(T--){
scanf("%d",&a);
b=1;
memset(s,0,sizeof(s));
int tmp=a;
top=0;
for(int i=1;i<=prime[0];i++){
top++;
if(tmp%prime[i]!=0) continue;
while(tmp%prime[i]==0){
s[top]++;
tmp/=prime[i];
if(tmp==1) break;
}
}
if(tmp>1){
top++;
s[top]++;
}
ans=1;
for(int i=1;i<=top;i++){
int bb=(s[i]+2)*(s[i]+1)/2;
int tt=bb*bb;
ans=ans*tt;
}
printf("%d\n",ans);
}
return 0;
}
形似八数码,但是是旋转。
宽搜+hash即可。
倒霉的是我没用一个数记状态,导致超时。这里感谢@唐泽皓
贴上他的代码。
#include
#include
#include
using namespace std;
using namespace std;
const int BIT[] = {1,2,4,5};
const int MAX = 362882;
int s[9] = { 1,10,100,1000,10000,100000,1000000,10000000,100000000 };
int jie[9] = { 0,1,2,6,24,120,720,5040,40320 };
int vis[MAX];
int len[MAX];
int four[4];
int lu(int num){
int result;
result = num%s[4];
result += ((num / s[5]) % 10)*s[4];
result += num / s[8] * s[5];
result += ((num / s[6]) % 10)*s[6];
result += ((num / s[4]) % 10)*s[7];
result += ((num / s[7]) % 10)*s[8];
return result;
}
int ru(int num){
int result = num / s[5] * s[5];
result += num / s[1] % 10;
result += num / s[4] % 10 * s[1];
result += num / s[2] % 10 * s[2];
result += num % 10 * s[3];
result += num / s[3] % 10 * s[4];
return result;
}
int ld(int num){
int result = num / s[6] * s[6] + num % 10;
result += num / s[2] % 10 * s[1];
result += num / s[5] % 10 * s[2];
result += num / s[3] % 10 * s[3];
result += num / s[1] % 10 * s[4];
result += num / s[4] % 10 * s[5];
return result;
}
int rd(int num){
int result = num % s[3] + num / s[8] * s[8];
result += num / s[4] % 10 * s[3];
result += num / s[7] % 10 * s[4];
result += num / s[5] % 10 * s[5];
result += num / s[3] % 10 * s[6];
result += num / s[6] % 10 * s[7];
return result;
}
int cantor(int key){
int result, temp[9];
for (int i = 8; i >= 0; i--){
temp[i] = key % 10;
key = key / 10;
}
result = 0;
for (int i = 0; i<8; i++){
int tot = 0;
for (int j = i + 1; j<9; j++)
if (temp[j]8 - i];
}
return result;
}
int key2[4];
int start = 123456789;
queue<int>que;
int main(){
int temp;
int key1;
len[0] = 0;
que.push(start);
vis[0] = 1;
while (!que.empty()){
temp = que.front();
que.pop();
key1 = cantor(temp);
four[0] = lu(temp);
four[1] = ru(temp);
four[2] = ld(temp);
four[3] = rd(temp);
for (int i = 0; i<4; i++){
key2[i] = cantor(four[i]);
if (!vis[key2[i]]){
vis[key2[i]] = 1;
que.push(four[i]);
len[key2[i]] = len[key1] + 1;
}
}
}
int start[9];
while (~scanf("%d",&start[0])){
temp = start[0];
for (int i = 1; i<9; i++){
scanf("%d",&start[i]);
temp=start[i]+temp*10;
}
printf("%d\n", len[cantor(temp)]);
}
return 0;
}
G.FBI Tree
Time Limit: 1000 MS Memory Limit: 32768 K
Total Submit: 385 (214 users) Total Accepted: 197 (185 users) Special Judge: No
Description
FBI Tree的描述如下:
我们可以把由0和1组成的字符串分为3类,全0的串成为B串,全1的串成为I串,既含0又含1的串则称为F串。FBI树是一种二叉树,它的节点类型也包括F串节点、B串节点和I串节点三种。由一个 长度为2^N的01串S可以构造出一颗FBI树T,递归的构造方法如下:
(1) T的根节点为R,其类型与串S的类型相同。
(2) 若串S的长度大于1,将串S从中间分开,分为等长的左右子串S1和S2;由左子串S1构造R的左子树T1,由右子串S2构造R的右子树T2。
现在给出一个长度为2^N的01串,请用上述构造方法构造出一棵FBI树,并输出它的后续遍历序列。
Input
第一行为一个正整数T,表示测试数据组数。
每组测试数据第一行为一个整数N(0 <= N <= 10),第二行是一个长度为2^N的01串。
Output
输出FBI树的后续遍历序列。
Sample Input
2
1
10
3
10001011
Sample Output
IBF
IBFBBBFIBFIIIFF
递归。
#include
#include
#include
using namespace std;
char st[2048];
int n;
int print(int l,int r){
if(l==r){
putchar(st[l]=='1'?'I':'B');
return st[l]=='1';
}
int mid = (l + r) / 2;
int t1=print(l,mid);
int t2=print(mid+1,r);
if(t1==2||t2==2){
putchar('F');
return 2;
}
if(t1+t2==1){
putchar('F');
return 2;
}
if(t1==1&&t2==1){
putchar('I');
return 1;
}
if(t1==0&&t2==0){
putchar('B');
return 0;
}
}
int main(){
int T;
scanf("%d\n",&T);
while(T--){
scanf("%d\n",&n);
gets(st+1);
print(1,strlen(st+1));
puts("");
}
return 0;
}
I.行编辑器
Time Limit: 1000 MS Memory Limit: 32768 K
Total Submit: 1436 (511 users) Total Accepted: 453 (420 users) Special Judge: No
Description
这次我们要写一个简单的行编辑器,当按下‘#’时代表按下了一次退格符,当按下‘@’时代表一个退行符(使当前行的字符全部无效)。例如,假设从终端接收了这样的两行字符:
Whil#lr#e(s#*s)
outcha@putchar(*s=#++)
则实际有效的是下列两行:
While(*s)
putchar(*s++)
请你编写一个程序,输出实际有效的字符串。
Input
第一行是一个整数T,表示测试数据组数。
接下来每行为一个字符串(不含空格和任何空白),表示输入的原始字符串
Output
输出最终的正确字符串。
Sample Input
2
Whil#lr#e(s#*s)
outcha@putchar(*s=#++)
Sample Output
While(*s)
putchar(*s++)
#include
#include
#include
using namespace std;
char stack[10086];
char st[10086];
int main(){
freopen("input.txt","r",stdin);
int T;
scanf("%d\n",&T);
while(T--){
int top=0;
char ch;
gets(st);
for(int i=0;i<strlen(st);i++){
ch=st[i];
if(ch=='#'){
if(top) top--;
continue;
}
if(ch=='@'){
top=0;
continue;
}
stack[++top]=ch;
}
stack[++top]='\0';
printf("%s\n",stack+1);
}
return 0;
}
K.小明和字符串
Time Limit: 1000 MS Memory Limit: 32768 K
Total Submit: 1137 (438 users) Total Accepted: 395 (378 users) Special Judge: No
Description
小明这个人特别无聊,他喜欢把一个字符串以一个奇怪的姿势压缩起来。他会把连续的字符表示成字符和数字的形式,而且他用的数字还都是一位的!!!比如下面这个例子:"a12" 表示的是 "aaaa"。也就是说压缩后的字符串里的每个数字表示重复最后一个出现的字符数字次,就好像上面的例子。
现在给你一些被无聊的小明压缩过的字符串,你能还原它么?
Input
输入的第一行包括一个整数 T,表示数据的组数。
每组输入包括一行,一个字符串,表示被小明压缩过的字符串。长度不超过50。
Output
每组输出包括一行,一个字符串,表示你展开之后的字符串。
Sample Input
1
a5b6c12
Sample Output
aaaaaabbbbbbbcccc
模拟题。但是注意,字符不是只有abcd,ABCD被坑了一发。
#include
#include
using namespace std;
char st[10086];
int main(){
freopen("input.txt","r",stdin);
int T;
scanf("%d\n",&T);
while(T--){
gets(st);
int tp = 0;
int len=strlen(st);
while(tpint i = tp+1;
if(!('0'<=st[i]&&st[i]<='9') ){
putchar(st[tp]);
tp=i;
continue;
}
if('0'<=st[i]<='9'){
int x=st[i]-'0';
while('0'<=st[i+1]&&st[i+1]<='9'){
x = x + st[i+1]-'0';
i++;
}
for(int cnt=0;cnt<=x;cnt++) putchar(st[tp]);
tp = i + 1;
}
}
puts("");
}
return 0;
}
H.下雪啦
Time Limit: 4000 MS Memory Limit: 32768 K
Total Submit: 673 (148 users) Total Accepted: 7 (7 users) Special Judge: No
Description
陈月亮最喜欢的季节就是冬天了,这不看着窗外飘起了雪花,陈月亮开心的跑出屋来看雪。但是迷迷糊糊的陈月亮不知道自己是在做梦还是真的下起了雪。突然她想起了一句话,在真实世界中是没有两片一样的雪花的。于是你的任务就是比较这场雪中的所有雪花,如果出现了两朵完全一致的雪花,则证明陈月亮是在梦中。
每朵雪花用六个整数表示,范围在(1 – 10000000)之间,表示雪花六个花瓣的长度,六个整数的先后出现顺序可能是顺时针顺序也可能是逆时针顺序,并且可能是从任意一个花瓣开始的。比如说对同一个花瓣,描述方法可能是1 2 3 4 5 6 或者 4 3 2 1 6 5
Input
第一行为一个整数T,表示有T组测试数据。
每组测试数据第一行为一个整数N(0 < N <= 100000),表示雪花的数目。
接下来n行每行六个整数,描述一朵雪花。
Output
如果没有相同的雪花,输出“No two snowflakes are alike.”,否则输出“Twin snowflakes found.”
Sample Input
1
2
1 2 3 4 5 6
4 3 2 1 6 5
Sample Output
Twin snowflakes found.
自己用set做wa到死,后来看了下题解,没想到只是一个裸的和的hash,突然想死。
数据不卡么?
按这个算法写了一发,1A。估计是自己算法问题。
#include
#include
#include
#include
using namespace std;
const int BASE=90001;
int info[111111][6];
vector<int> HASH[BASE];
bool check(int a, int b){
for(int i=0;i<6;i++){
bool ok1=true,ok2=true;
for(int cnt=0;cnt<6;cnt++)
ok1=ok1&&(info[a][cnt]==info[b][(i+cnt)%6]);
for(int cnt=0;cnt<6;cnt++)
ok2=ok2&&(info[a][cnt]==info[b][(i+(6-cnt))%6]);
if(ok1||ok2) return 1;
}
return 0;
}
int main(){
freopen("input.txt","r",stdin);
int T;
cin>>T;
while(T--){
bool ok=0;
int n;
int i,j;
scanf("%d",&n);
for(int i=0;ifor(int j=0;j<6;j++)
cin>>info[i][j];
int sum,key;
for(int i=0;i0;i++){
sum = 0;
for(int j=0;j<6;j++) sum+=info[i][j];
key=sum%BASE;
for(int j=0;jif(check(HASH[key][j], i)){
puts("Twin snowflakes found.");
ok=1;
break;
}
}
HASH[key].push_back(i);
}
if(ok) continue;
puts("No two snowflakes are alike.");
}
return 0;
}
后记:最近状态有些低迷。题解就不写太详细了。先舒缓舒缓吧。要是继续这样,估计就要GG了。B题C题和J题感觉能写,先放在这边,以后再补。感觉不组队都不会打比赛了。唉,lets prepare for the worst.