看起来十分的简单,其实需要分情况讨论。而且题中说在距离大于k时可以选择掉头,当然也可以选择不掉头,同时如果小鲲以到达终点,那么之后其位置都不会改变。或者当距离大于k之后,HtBest开始掉头,但是在掉头途中发现距离又小于k时进行选择这样的。
#include<bits/stdc++.h>
using namespace std;
int main()
{
double l,k,v1,v2;
scanf("%lf%lf%lf%lf",&l,&k,&v1,&v2);
if (v2>=v1)
{
double t1=l/v1;
double t2=l/v2;
printf("%.2lf\n",t2-t1);
}
else
{
double dv=v1-v2;
double dt=k/dv;
double t1=l/v1;
double t2=dt*2;
double dl=l-t2*v1;
double t;
if (dl>=k)
t=min(t2-t1,l/v2-t1);
else
t=l/v2-t1;
printf("%.2lf\n",t);
}
return 0;
}
模拟,细心一点就好
#include<bits/stdc++.h>
using namespace std;
vector<long long> p;
int main() {
int n;
scanf("%d",&n);
for(int i=0;i<n;i++) {
long long t;
scanf("%lld",&t);
p.push_back(t);
}
int cnt=0;
for(int i=0;i<n;i++) {
int start=i+1;
while(start<n&&p[start]>=p[start-1])
start++;
if(start==n)
break;
if(start==(i+1))
continue;
while(start<n&&p[start]<=p[start]-1)
start++;
cnt++;
i=start-1;
}
printf("%d\n",cnt);
return 0;
}
求取树上直径,两遍DFS即可
#include<bits/stdc++.h>
using namespace std;
const int N = 1000050;
typedef struct
{
int to;
int pre;
}Line;
Line edge[2 * N];
int f1[N], f2[N],head[N];
int n,tot=1;
int ans = 0;
void Add_edge(int a, int b)
{
edge[tot].to = b;
edge[tot].pre = head[a];
head[a] = tot++;
}
namespace IO {
#define BUF_SIZE 100000
#define OUT_SIZE 100000
#define LL long long
//fread->read
bool IOerror = 0;
inline char nc() {
static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE;
if (p1 == pend) {
p1 = buf; pend = buf + fread(buf, 1, BUF_SIZE, stdin);
if (pend == p1) { IOerror = 1; return -1; }
//{printf("IO error!\n");system("pause");for (;;);exit(0);}
}
return *p1++;
}
inline bool blank(char ch) { return ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t'; }
inline void read(int &x) {
bool sign = 0; char ch = nc(); x = 0;
for (; blank(ch); ch = nc());
if (IOerror)return;
if (ch == '-')sign = 1, ch = nc();
for (; ch >= '0'&&ch <= '9'; ch = nc())x = x * 10 + ch - '0';
if (sign)x = -x;
}
};
void DFS(int now, int pre)
{
for (int i = head[now]; i; i = edge[i].pre)
{
int temp = edge[i].to;
if (temp== pre)
continue;
DFS(temp, now);
if (f1[now] < f1[temp] + 1)
{
f2[now] = f1[now];
f1[now] = f1[temp] + 1;
}
else
f2[now] = max(f2[now], f1[temp] + 1);
}
ans = max(ans, f1[now] + f2[now]);
}
int main()
{
int a, b;
IO::read(n);
for (int i = 1; i < n; i++)
{
IO::read(a); IO::read(b);
Add_edge(a, b);
Add_edge(b, a);
}
DFS(1, 0);
printf("%d\n", ans + 1);
}
这道题其实很简单,但是比赛的时候没有想到如何解决MLE,其实可以在一开始预处理记录当前位置上的字符前面有几个,之后直接查询就可以,有点可惜。
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e6+11;
char s[MAXN];
int num[MAXN];
bool vis[MAXN];
int main() {
int n,m;
scanf("%d%d",&n,&m);
scanf("%s",s);
for(int i=0;i<n;i++) {
if(!vis[i]) {
vis[i]=true;
int cnt=0;
for(int j=i;j<n;j++) {
if(s[j]==s[i]) {
cnt++;
num[j]=cnt;
vis[j]=true;
}
}
}
}
for(int i=0;i<m;i++) {
int t;
scanf("%d",&t);
t--;
printf("%d\n",num[t]);
}
return 0;
}
模拟
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1011;
int n,m;
int graph[MAXN][MAXN];
bool is_win(int x,int y) {
int cnt=0,sum=graph[x][y],x1=x,y1=y;
while(x1>=1&&graph[x1][y]==sum)
x1--,cnt++;
x1=x+1;
while(x1<=n&&graph[x1][y]==sum)
x1++,cnt++;
if(cnt>=5)
return true;
cnt=0;
while(y1>=1&&graph[x][y1]==sum)
y1--,cnt++;
y1=y+1;
while(y1<=n&&graph[x][y1]==sum)
y1++,cnt++;
if(cnt>=5)
return true;
x1=x,y1=y,cnt=0;
while(x1>=1&&x1<=n&&y1>=1&&y1<=n&&graph[x1][y1]==sum)
x1--,y1--,cnt++;
x1=x+1,y1=y+1;
while(x1>=1&&x1<=n&&y1>=1&&y1<=n&&graph[x1][y1]==sum)
x1++,y1++,cnt++;
if(cnt>=5)
return true;
x1=x,y1=y,cnt=0;
while(x1>=1&&x1<=n&&y1>=1&&y1<=n&&graph[x1][y1]==sum)
x1--,y1++,cnt++;
x1=x+1,y1=y-1;
while(x1>=1&&x1<=n&&y1>=1&&y1<=n&&graph[x1][y1]==sum)
x1++,y1--,cnt++;
if(cnt>=5)
return true;
return false;
}
int main() {
scanf("%d%d",&n,&m);
bool flag=false;
for(int i=0;i<m;i++) {
int x1,y1;
scanf("%d%d",&x1,&y1);
graph[x1][y1]=i%2+1;
if(!flag) {
if(is_win(x1,y1)) {
flag=true;
if(i%2==0)
printf("HtBest %d\n",i+1);
else
printf("WHZ %d\n",i+1);
}
}
}
if(!flag)
printf("UNK %d\n",m);
return 0;
}
这个题可真是把我难倒了,好好复习了一下set的操作,同时一开始无法删除元素也是很迷啊,万般无奈看了别人的题解发现先往集合中预添加几个较大的数字就可以了。
#include<bits/stdc++.h>
using namespace std;
inline bool rd(int &X)
{
X=0;int w=0;char ch=0;
while(!isdigit(ch))w|=ch=='-',ch=getchar();
while( isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
X=w?-X:X; return 1;
}
char pd[10];
int m,k,x;
set<int> s;
set<int> :: iterator it;
void add(int x)
{
it=s.lower_bound(x);
if(abs(*it-x)<=k) return ;
it--;
if(abs(*it-x)<=k) return ;
s.insert(x);
}
void del(int x)
{
for(it=s.lower_bound(x-k);it!=s.end();)
if(*it-x>k) {break;}
else
{
int now=*it;
it++;
s.erase(now);
}
}
bool ask(int x)
{
it=s.lower_bound(x);
if(abs(*it-x)<=k) return 1;
it--;
if(abs(*it-x)<=k) return 1;
return 0;
}
signed main()
{
rd(m),rd(k);
s.insert( 100000000);
s.insert(-100000000);
while(m--)
{
scanf("%s",pd); rd(x);
if(pd[0]=='a') add(x);
if(pd[0]=='d') del(x);
if(pd[0]=='q') ask(x) ? puts("Yes") : puts("No");
}
}
作的时候没看出是最小生成树,直接排序然后并查集判定就OK了
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e6+11;
int par[MAXN];
int rank1[MAXN];
struct node{
int a,b,v;
};
vector<node> p;
bool cmp(node a,node b) {
return a.v<b.v;
}
void init(int n)
{
for(int i=1;i<=n;i++) {
par[i]=i;
rank1[i]=0;
}
}
int find(int x)
{
if(par[x]==x)
return x;
else
{
return par[x]=find(par[x]);
}
}
void unite(int x,int y)
{
x=find(x);
y=find(y);
if(x==y)
return;
if(rank1[x]<rank1[y])
par[x]=y;
else
{
par[y]=x;
if(rank1[x]==rank1[y])
rank1[x]++;
}
}
bool same(int x,int y)
{
return find(x)==find(y);
}
int main() {
int n,m;
scanf("%d%d",&n,&m);
init(n);
for(int i=0;i<m;i++) {
node temp;
scanf("%d%d%d",&temp.a,&temp.b,&temp.v);
p.push_back(temp);
}
sort(p.begin(),p.end(),cmp);
int cnt=0,ans=0;
for(int i=0;i<p.size();i++) {
if(same(p[i].a,p[i].b))
continue;
else {
unite(p[i].a,p[i].b);
ans+=p[i].v;
cnt++;
}
if(cnt==(n-1))
break;
}
printf("%d\n",ans);
return 0;
}
Flody应该拥有姓名,运气好卡过去了(试了很多次)但是还是很大可能TLE
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1011;
const int inf=0x3f3f3f3f;
int graph[MAXN][MAXN];
void init() {
for(int i=1;i<=1000;i++) {
for(int j=1;j<=1000;j++) {
if(i==j)
graph[i][j]=0;
else
graph[i][j]=inf;
}
}
}
int main() {
init();
int n,m,s,t;
scanf("%d%d%d%d",&n,&m,&s,&t);
for(int i=0;i<m;i++) {
int a,b,v;
scanf("%d%d%d",&a,&b,&v);
graph[a][b]=graph[b][a]=min(graph[a][b],min(graph[b][a],v));
}
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
graph[i][j]=min(graph[i][j],graph[i][k]+graph[k][j]);
if(graph[s][t]==inf)
printf("-1\n");
else
printf("%d\n",graph[s][t]);
return 0;
}
给出了数列的递推公式,那么我们可以求取出数组的通项公式,使用待定系数法,最终通项公式为:
当k等于1时为等差数列,不为1时前半部分使用等比数列的求和公式
除法部分乘上这个数的逆元
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define P 1000000007
int n,k,p,i;
int Pow(int x,int y)
{
int s=1;
for(;y;y>>=1,x=(ll)x*x%P)
if(y&1)
s=(ll)s*x%P;
return s;
}
int main()
{
cin>>n>>k>>p;
if(k==1)
cout<<((ll)n*(n-1)/2%P*p+n)%P<<endl;
else
{
i=Pow(k-1,P-2);
cout<<((1+(ll)p*i)%P*(Pow(k,n)-1)%P*i-(ll)p*n%P*i%P+P)%P<<endl;
}
return 0;
}
每次小白月赛的都能有新的收获,自己还是太菜了