热身赛:
A.题意:几个小孩围成一圈,从一个人手里传出这个球,可能向左,可能向右,问经过m轮传递传回这个人的方法数
题目类型:dp
解法:第i轮球在第j个人手里的方法数,即dp[i][j] = dp[i-1][j-1] + dp[i-1][j+1] 注意一下边界处理
Code:
#include <iostream>
#include <cstdio>
#include<cstring>
#define ll long long
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define MAX 100005
using namespace std;
int n,m,p,q,tree[4*100005];
int cnt=0,res,dp[50][50];
int main()
{
cin>>n>>m;
dp[0][1]=1;
dp[1][1]=0;
dp[1][2]=1;
dp[1][n]=1;
for(int i=2;i<=m;i++)
{
for(int j=1;j<=n;j++)
{
if(j==1)
dp[i][j]=dp[i-1][2]+dp[i-1][n];
else if(j==n)
dp[i][j]=dp[i-1][1]+dp[i-1][n-1];
else
dp[i][j]=dp[i-1][j-1]+dp[i-1][j+1];
}
}
cout << dp[m][1] << endl;
return 0;
}
B.疯狂涂色****
题目类型:枚举优化//。。。神奇
题意:有n个格子的纸条,有m条指令,第i条指令是将第(p*i+q)%n+1与(q*i+p)%n+1之间的格子图为颜色i,问执行完m条指令后最后的纸条的状态,无色为0;
解法:起初思路是线段树,然后lazy标记,更新段颜色,没写出来。。好像还会超时。正规思路很神奇 1.因为后涂的颜色会覆盖之前的颜色,因次我们可以倒着时间顺序,更新颜色,有颜色的格子就不再更新了,这里要写一个函数用来找某一个格子i的下一个没涂颜色的格子的位置的函数,不断更新 2.同时,再利用(p*i+q)%n+1是周期为n的函数,及在n次之内这个区间,一定会将n个格子覆盖完,因此最多执行n次操作;
C.题意:有3个人求到一点的最短距离和
解法:之前傻了,其实可以从终点跑一次最短路,加起来即可//三次最短路加一下
正式赛:
A. Height Oldering
题意:先将队首的人放到那一排中,然后下一个人要找到比他高的第一个人,站到他前边,他后边的人就会退一步腾出空间(傻子一般的读题能力,这水题错的我一口老血);
解法:腾出空间的人,一定是比后来的那个人高的人,因此,我们只需要统计每一个数,前边比他高的人有几个,累加即可;
Code:
#include <iostream>
#include<cstdio>
#include<queue>
#include<map>
#include<stdlib.h>
#include<algorithm>
#define ll long long
using namespace std;
int n,a[25];
int T;
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
int cnt=0;
for(int i=1;i<=20;i++)
{
scanf("%d",&a[i]);
}
for(int i=1;i<20;i++)
{
for(int j=i+1;j<=20;j++)
{
if(a[i]>a[j])cnt++;
}
}
cout <<n<<' '<< cnt << endl;
}
return 0;
}
B.这题暴力很好写,不说了;
C.Happy Prime Prime
题意:找出给定范围内符合条件数字的个数;
题意:初步思路:直接判断这个数是否符合条件,若是将这个数产生的数字全部标记为1,否标记为0,如果这个数字被使用过直接返回该值,否就重复上述步骤,避免了重复搜索,将该范围内符合条件的,数字打表;
好写(神)思路:数据范围是10000,猜下x,当一个数字循环某x次时,一定不符合条件,既然这样x就可以选择,刚好跑到时间上限就结束,好像x=50就够了(orz);
Code:
#include <iostream>
#include<cstdio>
#include<queue>
#include<map>
#include<stdlib.h>
#include<algorithm>
#include<cstring>
#define ll long long
using namespace std;
int n,m,a[25];
int T,jd[10005];
bool ispr[10005];
void Es()
{
memset(ispr,true,sizeof(ispr));
ispr[1]=false;
for(int i=2; i<=10003/i; i++)
{
if(ispr[i])
{
for(int j=i*i; j<10003; j+=i)
{
ispr[j]=false;//printf("%d\n",i);
}
}
}
}
/
int used[10005];
int judge(int m)
{
int flag=0;
if(!ispr[m])
return 0;
int tr=0,tm=m;
for(int i=0;i<50; i++)
{
while(tm)
{
tr+=(tm%10)*(tm%10);
tm/=10;
}
if(tr==1)
return 1;
tm=tr;
tr=0;
}
return 0;
}
int main()
{
Es();
memset(jd,-1,sizeof(jd));
memset(used,0,sizeof(used));
for(int i=1; i<=10005; i++)
{
if(jd[i]==-1)
{
jd[i]=judge(i);//printf("---%d %d\n",i,jd[i]);
}
}
//printf("%d %d %d %d\n",used[367],judge(367),jd[367],ispr[367]);
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
if(jd[m]==1)printf("%d %d YES\n",n,m);
else printf("%d %d NO\n",n,m);
}
return 0;
}
D.Mancala
题意:每次输出第x种情况,的最后一个格子的数目,和从第一个到这一个的序列,向左扫遇到第i个数目为i时,将这个格子分给前 i - 1个格子,和开头的箱子,如果最终全部可以在箱子里,则这个数列符合要求;
解法:倒着想,从左向右扫,碰到第i个格子为0则将其加i,前面的格子都取走一个,递推打表即可;
#include <iostream>
#include<cstdio>
using namespace std;
int a[2005][85];
int n,m;
int main()
{
a[1][1]=1;
a[2][1]=0,a[2][2]=2;
a[3][1]=1,a[3][2]=2;
a[4][1]=0,a[4][2]=1,a[4][3]=3;
for(int i=2 ; i <= 2000 ; i++ )
{
int j;
for(j =1 ; j <= 85 ; j++ )
{
if(a[i-1][j] == 0)
{
a[i][j] = j ;//printf("%d ",a[i][j]);
break;
}
else
{
a[i][j] = a[i-1][j]-1;//printf("%d ",a[i][j]);
}
}
j++;
for( ; j <= 85 ; j++ )
{
a[i][j] = a[i-1][j] ;
//printf("%d ",a[i-1][j]);
}
// printf("\n");
}
int x,T;
scanf("%d",&T);
for( int C = 1 ; C <= T ; C ++ )
{
scanf("%d%d",&n,&x);
int sum = 0 ,k = 0 ,res1 ;
for( ; sum < x ; )
{
sum+=a[x][k];
res1=a[x][k];
k++;
}
int y=0;
printf("%d %d\n", C, res1);
for(int i=1;i<k;)
{
int flag = 0;
for( y = 0 ; y < 10 && i < k ; y ++ , i ++ )
{
if(flag)printf(" ");
flag=1;
printf("%d",a[x][i]);
}
printf("\n");
if(i == k)break;
}
}
return 0;
}
E.A Rational Sequence
题意:根据图示,找到这个数的下一个数;
解法:当p<q时,输出p1=q , q=p-q;当p==q时,输出1/2;当p>q,向上找x层到一个父节点是左儿子的,算出他的下一个节点,向下找x层左节点,输出这个数;(样例的10000000给的是1ooooooo。。。然后又没按这个判。。。无力)
Code;
#include <iostream>
#include<cstdio>
#include<queue>
#include<map>
#include<stdlib.h>
#include<algorithm>
#include<cstring>
#define ll long long
//样例错了error
using namespace std;
int T,n;
void solve(ll p1,ll q1)
{
int cnt=0;
if(p1==q1)
{
printf("1/2\n");return;
}
else if(p1>q1)
{
if(q1==1)
{
printf("1/%lld\n",p1+1);
return ;
}
while(p1>q1)
{
p1=p1-q1;
cnt++;
}
int a,b;
a=p1,b=q1;
p1=b;
q1=b-a;
while(cnt--)
{
q1=p1+q1;
}
printf("%lld/%lld\n",p1,q1);
return ;
}
else if(p1<q1)
{
ll p=q1;
ll q=q1-p1;
printf("%lld/%lld\n",p,q);
return ;
}
}
ll p1,q1;
char s1[1000],s2[1000];
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d %d/%d",&n,&p1,&q1);
printf("%d ",n);
solve(p1,q1);
}
return 0;
}