题意:
给定一个数列 { a n } \{a_n\} { an} ,问 d ∣ ∏ i = l r a i d\mid\prod\limits_{i=l}^{r}a_i d∣i=l∏rai 是否成立,其中 d , l , r d,l,r d,l,r 都是给定正整数。
题解见队友博客,点击查看。
题意:
求满足 n a ⌈ log 2 n ⌉ b ⩽ k n^a\lceil\log_2n\rceil^b\leqslant k na⌈log2n⌉b⩽k 的整数 n n n 的最大值,其中 a , b ⩽ 10 , 1 0 6 ⩽ k ⩽ 1 0 18 a,b\leqslant 10,10^6\leqslant k\leqslant 10^{18} a,b⩽10,106⩽k⩽1018 是给定正整数。
题解见队友博客,点击查看。
题意:
给定一个有 m m m 条边的 n n n 顶有向图,其中任意一条从 u i u_i ui 到 v i v_i vi 的边具有两个相关值 a i , b i a_i,b_i ai,bi 。现欲从顶点 1 1 1 走到顶点 n n n ,每次经过一条边 e i e_i ei 的时候都要判断 cost = log 2 level + a i level ⩾ b i \text{cost}=\log_2\frac{\text{level}+a_i}{\text{level}}\geqslant b_i cost=log2levellevel+ai⩾bi 是否成立,成立才能通行。其中 level \text{level} level 的初始值为 1 1 1 ,且每经过一条边 e i e_i ei 都要增长 a i a_i ai 。
问是否存在从结点 1 1 1 到结点 n n n 的最短路径,如果存在,求最小总 cost \text{cost} cost 。
解法:
包装过的单源最短路径问题。
我们可以将到达结点 i i i 时的 level ∣ i \text{level}\mid_i level∣i 写成 1 + ∑ j ∈ G π , i a j 1+\sum\limits_{j\in G_{\pi,i}} a_j 1+j∈Gπ,i∑aj ,其中 G π , i G_{\pi,i} Gπ,i 表示顶点 i i i 在最短路径上的前驱子图。若记结点 i i i 在最短路径上的后继结点为 i ′ i' i′ ,则总的 cost \text{cost} cost 就可以写为
∑ i log 2 1 + ∑ j ∈ G π , i a j + a i 1 + ∑ j ∈ G π , i a j = log 2 ( ∏ i 1 + ∑ j ∈ G π , i ′ a j 1 + ∑ j ∈ G π , i a j ) = log 2 ( 1 + ∑ j ∈ G π , n a j ) = log 2 ( level ∣ n ) \begin{aligned} &\sum_i\log_2\frac{1+\sum\limits_{j\in G_{\pi,i}} a_j+a_i}{1+\sum\limits_{j\in G_{\pi,i}} a_j}\\ =&\log_2\left(\prod_i\frac{1+\sum\limits_{j\in G_{\pi,i'}} a_j}{1+\sum\limits_{j\in G_{\pi,i}} a_j}\right)\\ =&\log_2\left(1+\sum\limits_{j\in G_{\pi,n}} a_j\right)\\ =&\log_2(\text{level}\mid_{n})\end{aligned} ===i∑log21+j∈Gπ,i∑aj1+j∈Gπ,i∑aj+ailog2⎝⎜⎛i∏1+j∈Gπ,i∑aj1+j∈Gπ,i′∑aj⎠⎟⎞log2⎝⎛1+j∈Gπ,n∑aj⎠⎞log2(level∣n)
因此,只要求解以结点 1 1 1 为起点,以各边的 a i a_i ai 值为边权的单源最短路径即可。
值得注意的是,松弛过程中要记得判断当前边是否可取。
另外,在判断的时候还可以将式子两边乘方变为整数与 2 2 2 的次幂之间的比较,以提高精度。
参考代码:
#include
#include
#include
#include
typedef long long ll;
const ll INF=1e18;
const int MAXN=1e5+10;
int n,m;
struct qnode{
int v;
ll c;
qnode(int v=0,ll c=0):v(v),c(c){
}
bool operator<(const qnode &oth)const{
return c>oth.c;
}
};
struct Edge{
int v,a,b;
};
std::vector<Edge> G[MAXN];
ll dist[MAXN];
bool check(ll c,int a,int b){
return (1+a/c)>=((ll)1<<b);
}
std::priority_queue<qnode> pq;
void dijkstra(){
dist[1]=1;
pq.push(qnode(1,1));
qnode tmp;
while (!pq.empty()){
tmp=pq.top();pq.pop();
int u=tmp.v;
ll c=tmp.c;
if (dist[u]<c) continue;
for (int i=0;i<G[u].size();++i){
int v=G[u][i].v;
int cost=G[u][i].a;
int b=G[u][i].b;
if (check(c,cost,b)&&dist[v]>c+cost){
dist[v]=c+cost;
pq.push(qnode(v,dist[v]));
}
}
}
}
void init(){
while (!pq.empty()) pq.pop();
for (int i=1;i<=n;++i)
G[i].clear();
for (int i=1;i<=n;++i)
dist[i]=INF;
}
int main(){
int t;
scanf("%d",&t);
while (t--){
scanf("%d%d",&n,&m);
init();
for (int i=0;i<m;++i){
int u,v,a,b;
scanf("%d%d%d%d",&u,&v,&a,&b);
G[u].push_back((Edge){
v,a,b});
}
dijkstra();
ll res=dist[n];
if (res==INF) res=-1;
else res=floor(log2(res));
printf("%lld\n",res);
}
return 0;
}
题意:
给定两组数,求分别的最小值。
解法:
签到题, O ( n ) O(n) O(n) 算法求最值即可。
参考代码:
#include
const int INF=0x3f3f3f3f;
int main(){
int t;
scanf("%d",&t);
for (int x=1;x<=t;++x){
int n,m;
scanf("%d%d",&n,&m);
int y=INF,z=INF;
for (int i=0;i<n;++i){
int a;
scanf("%d",&a);
if (a<y) y=a;
}
for (int i=0;i<m;++i){
int b;
scanf("%d",&b);
if (b<z) z=b;
}
printf("Problem %d:\n",x+1000);
printf("Shortest judge solution: %d bytes.\n",y);
if (z!=INF)
printf("Shortest team solution: %d bytes.\n",z);
else printf("Shortest team solution: N/A bytes.\n");
}
return 0;
}
题意:
给定一个字符串,请你比较该字符串每个相邻后缀的字典序大小。
题解见队友博客,点击查看。
题意:
给定参赛选手的测评信息,请你按照一定要求做成直播面板。
解法:
格式化输出问题,照做即可。
参考代码:
#include
char s[20],t[20];
int main(){
int T;
scanf("%d",&T);
while (T--){
int rank,prob;
scanf("%d %s %d %s",&rank,s,&prob,t);
printf("%3d|%-16s|%d|[",rank,s,prob);
if (t[0]=='F') printf(" AC* ");
else if(t[0]=='R'&&t[1]=='u'){
int p;
scanf("%d",&p);
for (int i=0;i<p;i++)
printf("X");
for (int i=p;i<10;i++)
printf(" ");
}
else printf(" %-3s ",t);
puts("]");
}
return 0;
}