2018CCPC-女生专场
(咕咕咕,咕了快一年的bu题。。
A.CCPC直播
传送:http://acm.hdu.edu.cn/showproblem.php?pid=6297
题意:rt。
分析:模拟。
1 #include<bits/stdc++.h> 2 using namespace std; 3 int main(){ 4 int t; scanf("%d",&t); 5 while (t--){ 6 int pro,num; string rank,name,now; 7 cin >> rank; 8 cin >> name; 9 cin >> pro; 10 cin >> now; 11 if (now=="Running") cin >> num; 12 for (int i=0;i<3-rank.size();i++) cout << " "; 13 cout << rank << "|"; 14 cout << name; 15 for (int i=0;i<16-name.size();i++) cout << " "; 16 cout << "|"; 17 cout << pro << "|["; 18 if (now=="Running"){ 19 for (int i=0;i<num;i++) cout << "X"; 20 for (int i=0;i<10-num;i++) cout << " "; 21 } 22 else{ 23 for (int i=0;i<4;i++) cout << " "; 24 if (now=="FB"){ 25 cout << "AC*"; 26 for (int i=0;i<3;i++) cout << " "; 27 } 28 else{ 29 cout << now; 30 for (int i=0;i<10-now.size()-4;i++) cout << " "; 31 } 32 } 33 cout << "]\n"; 34 } 35 return 0; 36 }
B.口算训练
传送:http://acm.hdu.edu.cn/showproblem.php?pid=6287
题意:T(T<=10)组数据。给定n(n<=1e5)个数,a1,a2,....an(ai<=1e5)。m(m<=1e5)个询问,询问在区间[l,r[内所有数的乘积是否为k(k<=1e5)的倍数。
分析:(卡住了。。wsl
C.缺失的数据范围
传送:http://acm.hdu.edu.cn/showproblem.php?pid=6288
题意:求解最大的正整数n,满足公式:。数据范围:1<=a,b<=10,1e6<=k<=1e18。
分析:要求取得尽可能大的n。所以可以二分答案一直找尽可能大的n。注意,在check函数内,使用库函数log会有精度损失,需要手写log并上取整。
另,1e18相乘会爆ll,需要先除再比较大小。(wa了n发的坑点。。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 ll _log(ll n){ 5 ll ans=0; 6 while (1){ 7 if (n==1) return ans; 8 else if (n==2) return ans+1; 9 n-=n/2; 10 ans++; 11 } 12 } 13 bool check(ll xx,int a,int b,ll k){ 14 ll tmp=_log(xx); 15 ll num=1; 16 while (a--){ 17 if (num*tmp>k) return false; 18 num*=xx; 19 } 20 while (b--){ 21 if (num*tmp>k) return false; 22 num*=tmp; 23 } 24 return true; 25 } 26 int main(){ 27 int t; scanf("%d",&t); 28 int a,b; ll k,ans; 29 while (t--){ 30 scanf("%d%d%I64d",&a,&b,&k); 31 ll l=1,r=k,mid; 32 while (l<=r){ 33 mid=(l+r)/2; 34 if (check(mid,a,b,k)){ 35 ans=mid; l=mid+1; 36 } 37 else r=mid-1; 38 } 39 printf("%I64d\n",ans); 40 } 41 return 0; 42 }
D.
E.奢侈的旅行
传送:http://acm.hdu.edu.cn/showproblem.php?pid=6290
题意:n个点,m条单向路,每条路的描述为(u,v,a,b)。初始等级为1,通过每条路的要求为:通过这条路的花费为cost=,那么只有满足:时,才可以通过这条路。并且level提升a。问从1--n的最小花费。
分析:对于每一条边的通过限制条件,经过简单处理可以变成:。同时,对于每一次的花费相加(底数相同的log相加,真数相乘),化简之后可以变成:。所以在跑最短路时可以直接用ll来做,避免因为double的精度所导致的错误。
dijk+堆优化。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn=1e5+10; 5 const double inf=2e18; 6 struct edge{ 7 int to; 8 ll a,b; 9 }; 10 vector<edge> mp[maxn]; 11 struct node{ 12 int to; ll cost; 13 friend bool operator < (node p,node q){ 14 return p.cost>q.cost; 15 } 16 }; 17 int n,m; 18 bool vis[maxn]; ll dist[maxn]; 19 void dijk(){ 20 priority_queue<node> q; 21 for (int i=0;i<=n;i++) vis[i]=false,dist[i]=inf; 22 q.push({1,1.0}); 23 dist[1]=1; 24 while (!q.empty()){ 25 node tmp=q.top(); q.pop(); 26 if (vis[tmp.to]) continue; 27 vis[tmp.to]=true; 28 for (int i=0;i<mp[tmp.to].size();i++){ 29 edge res=mp[tmp.to][i]; 30 if (dist[res.to]>dist[tmp.to]+res.a && (dist[tmp.to]+res.a)/dist[tmp.to]>=(1ll<<res.b)){ 31 dist[res.to]=dist[tmp.to]+res.a; 32 q.push({res.to,dist[res.to]}); 33 } 34 } 35 } 36 } 37 int main(){ 38 int t; scanf("%d",&t); 39 int u,v; ll a,b; 40 while (t--){ 41 scanf("%d%d",&n,&m); 42 for (int i=1;i<=n;i++) mp[i].clear(); 43 for (int i=0;i<m;i++){ 44 scanf("%d%d%lld%lld",&u,&v,&a,&b); 45 mp[u].push_back({v,a,b}); 46 } 47 dijk(); 48 if (dist[n]==inf){ 49 printf("-1\n"); continue; 50 } 51 int num=0; 52 while (dist[n]){ 53 dist[n]/=2; 54 ++num; 55 } 56 printf("%d\n",num-1); 57 } 58 return 0; 59 }
F.对称数
传送:
题意:
分析:
G.赛题分析
传送:http://acm.hdu.edu.cn/showproblem.php?pid=6292
题意:rt。
分析:模拟。
1 #include<bits/stdc++.h> 2 using namespace std; 3 int main(){ 4 int t,n,m,x; scanf("%d",&t); 5 int _=1000; 6 while (t--){ 7 scanf("%d%d",&n,&m); 8 printf("Problem %d:\n",++_); 9 int ans=1e5; 10 for (int i=0;i<n;i++){ 11 scanf("%d",&x); 12 ans=min(ans,x); 13 } 14 printf("Shortest judge solution: %d bytes.\n",ans); 15 ans=1e5; 16 for (int i=0;i<m;i++){ 17 scanf("%d",&x); 18 ans=min(ans,x); 19 } 20 if (m!=0) printf("Shortest team solution: %d bytes.\n",ans); 21 else printf("Shortest team solution: N/A bytes.\n"); 22 } 23 return 0; 24 }
H.
I.SA-IS后缀数组
传送:http://acm.hdu.edu.cn/showproblem.php?pid=6294
题意:有一个长度为n的字符串,定义Si为以第i个字母开始的字符串后缀。求问,对于1<=i<n,Si与Si+1的字典序大小。
分析:思考一下。发现,只需要判断当前字符和下一个字符的大小关系即可,如果相同,就继续比较下一个位置。从后往前做即可。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e6+10; 4 char s[maxn],ans[maxn]; 5 int main(){ 6 int t,n; scanf("%d",&t); 7 while (t--){ 8 scanf("%d",&n); 9 scanf("%s",s); 10 ans[n-1]='>'; 11 for (int i=n-2;i>=0;i--){ 12 if (s[i]>s[i+1]) ans[i]='>'; 13 else if (s[i]<s[i+1]) ans[i]='<'; 14 else ans[i]=ans[i+1]; 15 } 16 for (int i=0;i<n-1;i++) printf("%c",ans[i]); 17 printf("\n"); 18 } 19 return 0; 20 }
J.回文树
传送:http://acm.hdu.edu.cn/showproblem.php?pid=6295
题意:有n个结点的树,每个点有一个值a[i],且a[i]的取值为1--n内随机的。求问,对于任意一对结点<u,v>,表示从u到v的树上的最短路径,路径上依此所经过的数字是回文串的点对数。
分析:因为ai取值随机。那么直接枚举回文串的中心即可(中心可以为点,也可以为一条边)。然后向两边不断扩展暴力即可。
同时注意题目中的限制条件,要求1<=u<=v<=n。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int maxn=1e5+10; 5 vector<int> mp[maxn]; 6 int a[maxn]; 7 bool cmp(int p,int q){return a[p]<a[q] || a[p]==a[q] && p<q;} 8 ll ans; 9 void dfs(int x,int fx,int y,int fy){ 10 if (a[x]!=a[y]) return ; 11 if (fx!=0 && x==y) return ; 12 if (x<=y) ans++; 13 int j=0,k; 14 for (int i=0;i<mp[x].size();i++){ 15 if (mp[x][i]!=fx){ 16 while (j<mp[y].size() && a[mp[y][j]]<a[mp[x][i]]) j++; 17 k=j; 18 while (k<mp[y].size() && a[mp[y][k]]<=a[mp[x][i]]) k++; 19 for (int t=j;t<k;t++) 20 if (mp[y][t]!=fy) dfs(mp[x][i],x,mp[y][t],y); 21 } 22 } 23 } 24 int main(){ 25 int t,n,x,y; scanf("%d",&t); 26 while (t--){ 27 scanf("%d",&n); 28 for (int i=1;i<=n;i++) scanf("%d",&a[i]),mp[i].clear(); 29 ans=0; 30 for (int i=0;i<n-1;i++){ 31 scanf("%d%d",&x,&y); 32 mp[x].push_back(y); 33 mp[y].push_back(x); 34 } 35 for (int i=1;i<=n;i++) sort(mp[i].begin(),mp[i].end(),cmp); 36 for (int i=1;i<=n;i++) dfs(i,0,i,0); //点作为回文中心 37 for (int i=1;i<=n;i++){ 38 for (int j=0;j<mp[i].size();j++){ 39 dfs(i,mp[i][j],mp[i][j],i); //边作为回文中心 40 } 41 } 42 printf("%lld\n",ans); 43 } 44 return 0; 45 }
K.