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 }
P6297

 

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 }
P6288

 

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 } 
P6290

 

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 }
P6292

 

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 } 
P6294

 

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 }
P6295

 

K.

posted @ 2019-03-01 19:42  Changer-qyz  阅读(770)  评论(0编辑  收藏  举报