Codeforces 1143
1143 B
题意
给你 \(n\) ,计算 \(f(n)=n\) 的每一个数码相乘得到的结果。( \(n\le 10^9\) )
Examples
input
390
output
216
input
7
output
7
input
1000000000
output
387420489
解
从右往左依次把每一位变成9,更新答案。
1143 C
题意
给你一棵树,有一些节点尊重它们的祖先,现在你要执行若干步,每步删除一个编号最小的点,满足它尊重它的祖先,且它的所有子节点(不是子树)尊重它。输出删除节点的序列。序列为空输出-1。( \(n\le 10^5\) )
Examples
input
5
3 1
1 1
-1 0
2 1
3 0
output
1 2 4
input
5
-1 0
1 1
1 1
2 0
3 0
output
-1
input
8
2 1
-1 0
1 0
1 1
1 1
4 0
5 1
7 0
output
5
解
一个节点删除后不会对任何节点产生影响。
所以找到初始状态所有满足条件的节点按顺序输出即可。
1143 D
题意
给一个有 \(n*k\) 个点的环,环上从 \(1\) 开始,每 \(k\) 个点有一个餐厅,你每次单向移动 \(L\) 个点,现在不知道你的初始位置和 \(L\) 的值,但是知道你初始位置离最近的餐厅的距离 \(a\) 和你第一次移动之后离最近的餐厅的距离 \(b\) 。你移动若干次后能回到起点,求这个值的最小值和最大值。( \(1\le n,k\le 100000,0\le a,b\le \frac{k}{2}\) )
Examples
input
2 3
1 1
output
1 6
input
3 2
0 0
output
1 3
input
1 10
5 3
output
5 5
解
首先我们钦定第一步时你在 \(a+1\) 处。
然后枚举所有可能的 \(b\) ,算出答案,更新。
有了第一步和第二步的位置怎么算答案?
设 \(t=(第一步位置-第二步位置)\% (n*m)\)
我们发现走的步数为 \(n*m/\gcd(t,n*m)\) (千万不要写成 \(\text{lcm}(t,n*m)/t\) ,会爆unsigned long long)
Code
#include<bits/stdc++.h>
using namespace std;
template<typename tp>
void read(tp& x){
x=0;
char c=getchar();
bool sgn=0;
while((c<'0'||c>'9')&&c!='-')c=getchar();
if(c=='-')sgn=1,c=getchar();
while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+c-'0',c=getchar();
if(sgn)x=-x;
}
template<typename tp>
void write(tp x){
if(x<0)putchar('-'),write(-x);
else{
if(x>=10)write(x/10);
putchar(x%10+'0');
}
}
typedef long long D;
D m,n,a,b;
D w(D x){return x?x:n*m;}
D gcd(D a,D b){return b==0?a:gcd(b,a%b);}
D solve(D x,D y){
D t=w((y+n*m-x)%(n*m));
D l=n*m/gcd(t,n*m);
return l;
}
int main(){
read(m),read(n),read(a),read(b);
D mi=LLONG_MAX,mx=LLONG_MIN;
for(D i=1,j=1+b,tmp;i<=m;i++,j+=n){
tmp=solve(1+a,j);
mi=min(mi,tmp);
mx=max(mx,tmp);
}
for(D i=1,j=n+1-b,tmp;i<=m;i++,j+=n){
tmp=solve(1+a,j);
mi=min(mi,tmp);
mx=max(mx,tmp);
}
write(mi),putchar(' '),write(mx);
return 0;
}
1143 E
题意
给你一个排列 \(p\) 和数组 \(a\) ,有 \(t\) 组询问,每次询问一个区间的子序列中是否有 \(p\) 的一个循环排列。( \(1≤|p|,|a|,t≤2*10^5\) )
Examples
input
3 6 3
2 1 3
1 2 3 1 2 3
1 5
2 6
3 5
output
110
input
2 4 3
2 1
1 1 2 2
1 2
2 3
3 4
output
010
解
处理出 \(a\) 中每个元素 \(a[i]\) 的前驱 \(pre[i]\) ,前驱定义为值为在排列中对应 \(a[i]\) 的上一个元素,且最靠近 \(a[i]\) 的数
\(dp[i]=dp[pre[i]]+1\)
我们发现形成了森林
然后需要处理出 \(a[i]\) 上面第 \(n\) 个祖先,可以用倍增,也存到一个数组 \(s[i]\) 中
询问时查询 \([l,r]\) 区间中是否存在 \(i\) 使得 \(s[i]>=l\) ,用线段树或者其他数据结构维护。
1143 F
题意
平面上有 \(n\) 个点,求有多少条不同的抛物线 \(y=x^2+bx+c(b,c\in R)\) ,满足没有点严格在其上方。( \(n\le 10^5\) )
Examples
input
3
-1 0
0 2
1 0
output
2
input
5
1 0
1 -1
0 -1
-1 0
-1 -1
output
1
解
首先将所有点的坐标减去横坐标的平方
于是抛物线退化成了直线
用上凸包维护
注意特判两个点横坐标相同的情况