Problem A: M1crosoft Exce1
直接的模拟题,代码:
#include
using namespace std;
struct stu
{
string text;
int align;
struct stu *f;
} p[30][30],*self;
int main()
{
//freopen("in.txt", "r", stdin);
int t,n,m,d,k,i,j,flag,b,y;
char s[10],ch[300];
char a,x;
cin>>t;
while(t--)
{
for(i=0; i<30; i++)
{
for(j=0; j<30; j++)
{
p[i][j].text="";
p[i][j].f=&p[i][j];
p[i][j].align=0;
}
}
cin>>n>>m>>d>>k;
while(k--)
{
scanf("%s",s);
getchar();
if(strcmp(s,"text")==0)
{
scanf("%c%d ",&a,&b);
fgets(ch,300,stdin);
ch[strlen(ch)-1]='\0';
p[a-'A'+1][b].text=ch;
}
else if(strcmp(s,"align")==0)
{
scanf("%c%d%s",&a,&b,ch);
if(strcmp(ch,"left")==0)
{
p[a-'A'+1][b].align=0;
}
else if(strcmp(ch,"right")==0)
{
p[a-'A'+1][b].align=1;
}
}
else if(strcmp(s,"merge")==0)
{
scanf("%c%d %c%d",&a,&b,&x,&y);
for(i=a; i<=x; i++)
{
for(j=b; j<=y; j++)
{
p[i-'A'+1][j].f=&p[x-'A'+1][y];
}
}
}
}
for(i=-m-1; itext.length()align==1)
{
for(k=d-self->text.length(); k>0; k--)
{
cout<<" ";
}
cout<text;
}
else if(self->align==0)
{
cout<text;
for(k=d-self->text.length(); k>0; k--)
{
cout<<" ";
}
}
self->text="";
}
else
{
if(self==&p[i][j])
{
flag=1;
}
cout<text.substr(0,d);
self->text=self->text.substr(d);
}
if(j==m||p[i][j].f!=p[i][j+1].f)
{
cout<<"|";
}
else
{
if(self->text.length()==0)
{
cout<<" ";
}
else
{
cout<text.substr(0,1);
self->text=self->text.substr(1);
}
}
}
cout<text.length()align==1)
{
for(k=d-self->text.length(); k>0; k--)
{
cout<<" ";
}
cout<text;
}
else if(self->align==0)
{
cout<text;
for(k=d-self->text.length(); k>0; k--)
{
cout<<" ";
}
}
self->text="";
}
else
{
cout<text.substr(0,d);
self->text=self->text.substr(d);
}
}
if(i==n||p[i][j].f!=p[i+1][j].f||p[i][j].f!=p[i][j+1].f)
{
cout<<"-";
}
else
{
self=p[i][j].f;
if(self->text.length()==0)
{
cout<<" ";
}
else
{
cout<text.substr(0,1);
self->text=self->text.substr(1);
}
}
}
cout<
Problem B: J VS B
题解:简单的博弈题,考虑k>1时一定是yes;k=1时判断n的奇偶
代码:
#include
using namespace std;
int main()
{
//freopen("test01.in","r",stdin);
//freopen("test01.out","w",stdout);
int n,k;
int T;
while(scanf("%d",&T)!=EOF){
while(T--){
scanf("%d%d",&n,&k);
if(k>1)
printf("yes\n");
else{
if(n%2==0)
printf("no\n");
else
printf("yes\n");
}
}
}
return 0;
}
Problem C: Jinixin Speech
题解:给你n个数,m次询问,每次询问是这样的:
输入 x,将会构造出一个新的序列,这个新的序列b[i]=a[x]-a[i](iSum2输出Keep dis
如果sum1=sum2输出Next time
如果Sum1j的时候
Sum2+=a[x][j]*(j-s[x]) (s[x]
然后扫一遍10个数就好了~
代码:
#include
using namespace std;
long long a[100005][11];
int main()
{
long long i,j,n,m,x,tmp,A,B;
string s;
while(~scanf("%lld%lld",&n,&m))
{
memset(a,0,sizeof(a));
cin>>s;
for(i=0;itmp)
B+=(i-tmp)*a[x-1][i];
}
if(A==B)
printf("Next time\n");
else if(A>B)
printf("Keep some distance from me\n");
else
printf("I agree\n");
}
}
return 0;
}
Problem D: Group Sum
题解:
题意:
给定一个数M,从1~9这9个数中选出M个不同的数,组成一个集合。
当集合中所有元素之和等于N时,输出该集合,要求找到所有满足条件的集合。
注:集合之间从小到大排序,集合内元素也要从小到大排序。
想法:
拿到题,因为集合中的元素来自1~9,且要求有序输出,所以很容易想到用循环嵌套来做,但因为题中M不确定,故用M个循环解决本题可能比较麻烦。循环与递归在某种程度上是可以相互转换的,故我们通过递归来思考本题。
vector minums;
void dfs(int i,int m)
{
if(m==(int)minums.size())
{
//找到了一个长度为m的集合
return;
}
for(i++;i<=9;i++)
{
minums.push_back(i);//将i加入minums集合末尾
dfs(i,m);
minums.pop_back();//将minums集合末尾的元素删除
}
}
调用:dfs(0,m);
通过上述代码可以找到所有长度为m的集合。
minums集合中的元素满足从小到大的顺序,且找到的长度为m的集合的先后顺序也满足从小到大。
下面我们只要着手判断该集合内所有元素之和是否等于n?如果等于n则把该集合再存储进一个大集合即可。
vector minums;
vector> nums;//大集合
void dfs(int i,int m,int n)
{
if(n<0)//集合中元素之和已经超过n
{
return;//返回
}
if(m==(int)minums.size())//找到了一个长度为m的集合
{
if(n==0)//如果集合中所有元素之和等于n,则该集合minums符合要求
{
nums.push_back(minums);//将minums存储到集合nums中
}
return;//返回
}
for(i++;i<=9;i++)
{
minums.push_back(i);//将i加入minums集合末尾
dfs(i,m,n-i);
minums.pop_back();//将minums集合末尾的元素删除
}
}
调用:dfs(0,m,n);
nums集合即为最终答案。
代码:
#include
#include
using namespace std;
vector minums;
vector> nums;
void dfs(int i,int k,int n)
{
if(n<0)
{
return;
}
if(k==(int)minums.size())
{
if(n==0)
{
nums.push_back(minums);
}
return;
}
for(i++;i<=9;i++)
{
minums.push_back(i);
dfs(i,k,n-i);
minums.pop_back();
}
}
int main()
{
int k,n,i,j;
while(~scanf("%d%d",&k,&n))
{
nums.clear();
minums.clear();
dfs(0,k,n);
cout<<"[";
for(i=0;i<(int)nums.size();i++)
{
cout<<"[";
for(j=0;j
Problem E: Binary Tree
题意:
按层序给你一棵二叉树各节点值的序列(空节点值为null),要求建立该二叉树,并判断该二叉树是否具有对称性。
如果具有对称性,输出1。
如果不具有对称性,输出0,并输出该二叉树的先序遍历序列。
想法:
本题是模拟题,涉及“字符串处理”,“二叉树建树”,“先序遍历”。
注1:给定的序列是“A B C D ”这样的形式,字母表示节点的值,节点值后面一定有一个空格。
注2:题中说明“节点值为整数”,但大家需要考虑到负整数的情况!
****************************************************************************************************
//数据结构定义
struct TreeNode {
int val;
TreeNode *left,*right;
};
****************************************************************************************************
//将读入的序列转换为二叉树
TreeNode* deserialize(string data)
{
TreeNode *root,*head,*pre;
queue p;
int i=0,j=0,flag=1;//flag为0表示节点为空;为1表示正数;为-1表示负数。
//由于需要知道所建树的根节点地址,故单独先读第一个数!
while(data[i]!=' '&&ival=j*flag;//flag表示正负!
head->left=head->right=NULL;
p.push(head);//压入队列
}
while(!p.empty())
{
pre=p.front();//从队列中读出一个节点作为根节点
p.pop();
j=0;flag=1;i++;
while(data[i]!=' '&&ileft=NULL;
}
else if(ival=j*flag;
root->left=root->right=NULL;
pre->left=root;//根的左孩子即为该数所在节点
p.push(root);//将该数所在节点压入队列
}
j=0;flag=1;i++;
while(data[i]!=' '&&iright=NULL;
}
else if(ival=j*flag;
root->left=root->right=NULL;
pre->right=root;//根的右孩子即为该数所在节点
p.push(root);//将该数所在节点压入队列
}
}
return head;//返回所建树根节点的地址
}
调用:deserialize(传入序列);
****************************************************************************************************
//判断序列是否具有对称性
bool flag;
void dfs(struct TreeNode *Tleft,struct TreeNode *Tright)
{
if(!flag)
{
return;
}
if(Tleft->val!=Tright->val)//左子树和右子树根节点值不相等,不对称!
{
flag=false;
return;
}
if(Tleft->right&&Tright->left)//“左子树的右子树”和“右子树的左子树”都存在
{
dfs(Tleft->right,Tright->left);//递归,进一步判断“左子树的右子树和右子树的左子树”
}
else if(!Tleft->right&&!Tright->left)//“左子树的右子树”和“右子树的左子树”都不存在,对称
{
;
}
else//“左子树的右子树”或“右子树的左子树”不存在,不对称!
{
flag=false;
return;
}
if(Tleft->left&&Tright->right)//同理判断“左子树的左子树和右子树的右子树”
{
dfs(Tleft->left,Tright->right);
}
else if(!Tleft->left&&!Tright->right)
{
;
}
else
{
flag=false;
return;
}
}
bool isSymmetric(struct TreeNode* root)
{
flag=true;
if(root)
{
if(root->right&&root->left)//树的根节点有左子树和右子树
{
dfs(root->left,root->right);//进一步判断树的左右子树情况
}
else if(!root->right&&!root->left)//树的根节点没有左子树和右子树,对称
{
;
}
else//树的根节点没有左子树或右子树,一定不对称!
{
flag=false;
}
}
return flag;
}
调用:isSymmetric(传入二叉树根节点地址);
****************************************************************************************************
//先序遍历二叉树
void tlr(struct TreeNode* root)
{
if(root)
{
//操作root->val的语句写在这里,本题为“cout<val;”
tlr(root->left);
tlr(root->right);
}
}
调用:tlr(传入二叉树根节点地址);
代码:
#include
#include
#include
using namespace std;
struct TreeNode {
int val;
struct TreeNode *left,*right;
};
int flag;
TreeNode* init(string data)
{
TreeNode *root,*head,*pre;
queue p;
int i=0,j=0,flak=1;
while(data[i]!=' '&&ival=j*flak;
head->left=head->right=NULL;
p.push(head);
}
while(!p.empty())
{
pre=p.front();
p.pop();
j=0;flak=1;i++;
while(data[i]!=' '&&ileft=NULL;
}
else if(ival=j*flak;
root->left=root->right=NULL;
pre->left=root;
p.push(root);
}
j=0;flak=1;i++;
while(data[i]!=' '&&iright=NULL;
}
else if(ival=j*flak;
root->left=root->right=NULL;
pre->right=root;
p.push(root);
}
}
return head;
}
void dfs(struct TreeNode *Tleft,struct TreeNode *Tright)
{
if(!flag)
{
return;
}
if(Tleft->val!=Tright->val)
{
flag=false;
return;
}
if(Tleft->right&&Tright->left)
{
dfs(Tleft->right,Tright->left);
}
else if(!Tleft->right&&!Tright->left)
{
;
}
else
{
flag=false;
return;
}
if(Tleft->left&&Tright->right)
{
dfs(Tleft->left,Tright->right);
}
else if(!Tleft->left&&!Tright->right)
{
;
}
else
{
flag=false;
return;
}
}
int isSymmetric(struct TreeNode* root) {
flag=1;
if(root)
{
if(root->right&&root->left)
{
dfs(root->left,root->right);
}
else if(!root->right&&!root->left)
{
;
}
else
{
flag=0;
}
}
return flag;
}
void tlr(struct TreeNode *root)
{
if(!root)
{
return;
}
cout<val;
tlr(root->left);
tlr(root->right);
}
int main()
{
string s;
int num;
struct TreeNode *lead;
while(getline(cin,s))
{
lead=init(s);
num=isSymmetric(lead);
cout<
Problem F: The Clock of Station
题解:简单题代码:
#include
int main()
{
int T;
scanf("%d",&T);
while(T--){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
printf("%d\n",(x+y)*z);
}
return 0;
}
Problem G: Count beans will be crazy
题解:(这是一个小学奥数改编的题目)由题意可得本题即求最小公倍数,需考虑到long long,还有直接打出来也是可以的
代码:
#include
long long gcd(long long n,long long m)
{
long long a=n,b=m,r=a%b;
while(r)
{
a=b;
b=r;
r=a%b;
}
return n/b*m;
}
int main()
{
int n,i;
long long f[45];
f[2]=2;
for(i=3;i<=40;i++)
{
f[i]=gcd(f[i-1],i);
}
while(~scanf("%d",&n))
{
printf("%lld\n",f[n]-1);
}
return 0;
}
Problem H: Math
题解:此题数据有点虚了,换一种思路可以直接搞。提供本来自己思路的代码
代码:
#include
using namespace std;
int T,n,k;
int p[]={2,3,5,7,11,13,17,19,23,29,31};
int sum[11],s[11];
void solve()
{
memset(sum,0,sizeof(sum));
memset(s,0,sizeof(s));
if(n<2)
return;
int i,j;
for(i=0;i<11;++i)
{
j=n;
while(j)
{
sum[i]+=(j/=p[i]);
}
}
}
int calc()
{
if(n<2)
return 0;
int ans=0x7fffffff;
int i,j;
for(i=0;i<11;++i)
{
while(!(k%p[i]))
{
k/=p[i];
++s[i];
}
}
for(i=0;i<11;++i)
{
if(!s[i])
continue;
ans=min(ans,sum[i]/s[i]);
}
return ans;
}
int main()
{
//freopen("test01.in","r",stdin);
//freopen("test01.out","w",stdout);
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&k);
//cin>>n>>k;
solve();
printf("%d\n",calc());
//cout<
Problem I: Jinixin -> Mosu
题意:
在一个二维数组中寻找最长的递增序列长度,该二维数组长度最大可至1000*1000。
想法:
根据题意,大致确定这是一道搜索题,由于寻找的是“最长递增序列长度”,判断应该用迷宫类型的dfs,故直接套模板。
const int N=1000;
int p[N][N],vis[N][N],dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
int max,n,m;
void dfs(int x,int y,int t)//迷宫类dfs模板,t为现在“递增序列”的长度
{
int i,a,b;
max=max>t?max:t;//更新max,max为目前“最长递增序列长度”
for(i=0;i<4;i++)
{
a=x+dir[i][0];//根据所处X坐标,产生前进方向的X坐标
b=y+dir[i][1];//根据所处Y坐标,产生前进方向的Y坐标
if(a>=0&&a=0&&bp[x][y])//判断前进方向坐标是否合法,是否未走过,是否递增
{
vis[a][b]=1;//p[a][b]已经走过
dfs(a,b,t+1);
vis[a][b]=0;//p[a][b]重新标记未走过
}
}
}
int longestIncreaseRoute()
{
int i,j;
max=0;
memset(vis,0,sizeof(vis));//vis用于判断该位置是否已经走过
scanf("%d%d",&n,&m);
for(i=0;i
注:寻找“最长递增序列长度”和寻找“最长递减序列长度”是等价的!
const int N=1000;
int p[N][N],vis[N][N],store[N][N],dir[4][3]={{-1,0},{1,0},{0,-1},{0,1}};//store数组用于记忆化
int dfs(int x,int y)
{
int i,a,b,sum=1;//sum为从该位置出发的“最长递减序列长度”
for(i=0;i<4;i++)
{
a=x+dir[i][0];
b=y+dir[i][1];
dir[i][2]=1;
if(a>=0&&a=0&&bdir[i][2]?sum:dir[i][2];//四个方向中选取最大的值
}
store[x][y]=sum;//记忆化,从该位置(x,y)出发的“最长递减序列长度”
return sum;
}
int longestIncreaseRoute()
{
int i,j;
int max=0;
memset(vis,0,sizeof(vis));
memset(store,0,sizeof(store));
scanf("%d%d",&n,&m);
for(i=0;istore[i][j]?max:store[i][j];//找出“最长递减序列长度”
}
}
return max;
}
调用:longestIncreaseRoute();
“迷宫类dfs+记忆化”可以高效的解决本题。
代码:
#include
#include
#include
using namespace std;
const int M=1005;
int p[M][M],vis[M][M],store[M][M],dir[4][3]={{-1,0},{1,0},{0,-1},{0,1}};
int n,m;
int dfs(int x,int y)
{
int i,a,b,sum=1;
for(i=0;i<4;i++)
{
a=x+dir[i][0];
b=y+dir[i][1];
dir[i][2]=1;
if(a>=0&&a=0&&bdir[i][2]?sum:dir[i][2];
}
store[x][y]=sum;
return sum;
}
int path()
{
int i,j,max=0;
for(i=0;istore[i][j]?max:store[i][j];
}
}
return max;
}
int main()
{
//freopen("test1.in","r",stdin);
//freopen("test1.out","w",stdout);
int i,j;
while(~scanf("%d%d",&n,&m))
{
memset(vis,0,sizeof(vis));
memset(store,0,sizeof(store));
for(i=0;i
Problem J: Jinixin's password
题解:首先我们判断是否能由n个数构成m。
数据比如 3 0,1 19这种,就不能构成
然后我们就可以贪心了~
最小的数,肯定是由1000000000这种,然后从低位开始增加,直到达到m为止
而最大的数,则是由9999999999这种,从低位到高位,逐渐减小,直到变成m
比如 4 27这组数据
首先贪心最小的:
目前的数 目前的sum
1000 1
1009 10
1099 19
1899 27
贪心最大的:
目前的数 目前的sum
9999 36
9990 27
所以输出1899 9990
代码:
#include
#include
using namespace std;
int flag;
int n,m;
int Min[120];
int Max[120];
void getmin()
{
int sum = 0;
for(int i=1;i<=n;i++)
{
if(i==1)Min[i]=1;
else Min[i]=0;
sum += Min[i];
}
sum = m - sum;
for(int i=n;i>=1;i--)
{
int T = min(sum,9-Min[i]);
sum -= T;
Min[i] += T;
}
if(Min[1]==0)flag = 1;
}
void getmax()
{
int sum = 0;
for(int i=1;i<=n;i++)
{
Max[i]=9;
sum+=Max[i];
}
sum = sum - m;
for(int i=n;i>=1;i--)
{
int T = min(sum,Max[i]);
sum-=T;
Max[i]-=T;
}
if(Max[1]==0)flag = 1;
}
int main()
{
int t;
scanf("%d",&t);
for(int cas=1;cas<=t;cas++)
{
scanf("%d%d",&n,&m);
flag = 0;
if(n==1&&m==0)
{
printf("0 0\n");
continue;
}
if(n*9