AtCoder Beginner Contest 190

传送门:https://atcoder.jp/contests/abc190

 

A:

Takahashi和Aoki分别有A和B颗糖果,两人轮流吃一个,若C为0则Takahashi先吃,C为1则Aoki先吃,先吃完的为输。

 

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <vector>
 4 #include <algorithm>
 5 #include <queue>
 6 #include <vector>
 7 #include <map>
 8 #include <cstdlib>
 9 #include <cstring>
10 #include <cmath>
11 typedef long long ll;
12 const int INF=0x3f3f3f3f;
13 using namespace std;
14 int a,b,c;
15 int main(void)
16 {
17     cin>>a>>b>>c;
18     if(c==0)
19     {
20         if(a>b)cout<<"Takahashi"<<endl;
21         else cout<<"Aoki"<<endl;
22     }
23     else
24     {
25         if(a<b)cout<<"Aoki"<<endl;
26         else cout<<"Takahashi"<<endl;
27     }
28     return 0;
29 }

B:

Takahashi有N段符咒,每段需要吟唱Xi秒,伤害为Yi,而怪兽能免疫吟唱时间在S秒及以上和伤害在D及以下的符咒,问能否对怪兽造成伤害。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <vector>
 4 #include <algorithm>
 5 #include <queue>
 6 #include <vector>
 7 #include <map>
 8 #include <cstdlib>
 9 #include <cstring>
10 #include <cmath>
11 typedef long long ll;
12 const int INF=0x3f3f3f3f;
13 using namespace std;
14 int n,s,d;
15 int main(void)
16 {
17     cin>>n>>s>>d;
18     while(n--)
19     {
20         int x,y;
21         cin>>x>>y;
22         if(x>=s||y<=d)continue;
23         cout<<"Yes"<<endl;
24         return 0;
25     }
26     cout<<"No"<<endl;
27     return 0;
28 }

C:

有N个盘子和M个状态,第i个状态满足当且仅当第Ai和第Bi个盘子上有一个以上的球。有K个人,每个人可以把一个球放在第Ci或者第Di个盘子上。求能满足的最多状态数。

分析:由于K<=16,那么总的情况数只有216种,因此可以直接暴搜,每次更新答案即可。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <vector>
 4 #include <algorithm>
 5 #include <queue>
 6 #include <vector>
 7 #include <map>
 8 #include <cstdlib>
 9 #include <cstring>
10 #include <cmath>
11 typedef long long ll;
12 const int INF=0x3f3f3f3f;
13 using namespace std;
14 int n,m,a[1000][2],b[1100],c[1000][2],k,ans;
15 void dfs(int t)
16 {
17     if(t==k+1)
18     {
19         int cnt=0;
20         for(int i=1;i<=m;++i)
21         {
22             if(b[a[i][0]]&&b[a[i][1]])cnt++;
23         }
24         ans=max(cnt,ans);
25     }
26     else
27     {
28         b[c[t][0]]++;
29         dfs(t+1);
30         b[c[t][0]]--;
31         b[c[t][1]]++;
32         dfs(t+1);
33         b[c[t][1]]--;
34     }
35 }
36 int main(void)
37 {
38     cin>>n>>m;
39     for(int i=1;i<=m;++i)
40     {
41         cin>>a[i][0]>>a[i][1];
42     }
43     cin>>k;
44     for(int i=1;i<=k;++i)
45     {
46         cin>>c[i][0]>>c[i][1];
47     }
48     dfs(1);
49     cout<<ans<<endl;
50     return 0;
51 }

D:

给定一个整数N,求有多少个公差为1的等差数列,使得数列和为N。

分析:我们只需考虑数列为正整数的情况,然后乘2即可。因为对于任意一个满足条件的正整数数列a1,a2,……,an,都可以在前面添加一个首项为-a1+1,末项为a1-1的等差数列,使得和仍为N。假设项数为i,那么有(1+i)*i<=2*N。我们枚举每个项数,判断是否合法。

(1)若i为奇数,仅需判断N是否整除i。

(2)若i为偶数:如果N为奇数,那么i不能为4的倍数;如果N为偶数,那么i应为4的倍数。同时对任意N,还要满足N整除i/2,而且N/(i/2)为奇数。

 

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <vector>
 4 #include <algorithm>
 5 #include <queue>
 6 #include <vector>
 7 #include <map>
 8 #include <cstdlib>
 9 #include <cstring>
10 #include <cmath>
11 #include <set>
12 #include <unordered_set>
13 typedef long long ll;
14 const int INF=0x3f3f3f3f;
15 using namespace std;
16 ll n,ans;
17 int main(void)
18 {
19     cin>>n;
20     for(ll i=1;i*i+i<=2*n;++i)
21     {
22         if(i&1)
23         {
24             if(n%i==0)ans+=2;
25         }
26         else
27         {
28             if(n%2==1&&i%4!=0&&n%(i/2)==0&&(n/(i/2))%2==1||n%2==0&&i%4==0&&n%(i/2)==0&&(n/(i/2))%2==1)ans+=2;
29         }
30     }
31     cout<<ans<<endl;
32     return 0;
33 }

 

E:

有N种宝石和M对组合,表示第Ai和Bi种宝石可以相邻。其他的不能相邻。给出K种需要的宝石,分别为C1,C2,……,Ck,是否存在一个序列满足K种宝石都出现一次及以上,若有输出需要的最小宝石数量。

分析:设dis[i][j]表示i和Cj的最小距离(可以通过对每种需要的宝石进行一次BFS求出),dp[i][state]表示以Ci结尾的状态为state时所需要的最少宝石数(例如state为101,表示序列中有C1和C3)。那么dp[i][state]=min(dp[j][state']+dis[Cj][i]),最终答案为min(dp[i][(1<<K)-1],0<=i<K)。

 

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <vector>
 4 #include <algorithm>
 5 #include <queue>
 6 #include <vector>
 7 #include <map>
 8 #include <cstdlib>
 9 #include <cstring>
10 #include <cmath>
11 #include <set>
12 typedef long long ll;
13 const int INF=0x3f3f3f3f;
14 using namespace std;
15 int n,m,k,dis[110000][18],arr[18];
16 int dp[18][(1<<18)];
17 vector<int>e[110000];
18 void bfs(int t)
19 {
20     for(int i=1;i<=n;++i)dis[i][t]=INF;
21     queue<int>que;
22     que.push(arr[t]);
23     dis[arr[t]][t]=0;
24     while(!que.empty())
25     {
26         int p=que.front();
27         que.pop();
28         for(int i=0;i<e[p].size();++i)
29         {
30             int v=e[p][i];
31             if(dis[v][t]==INF)
32             {
33                 dis[v][t]=dis[p][t]+1;
34                 que.push(v);
35             }
36         }
37     }
38 }
39 int solve(int last,int t)
40 {
41     if(t==((1<<k)-1))return 0;
42     int &ret=dp[last][t];
43     if(ret!=-1)return ret;
44     ret=INF;
45     for(int i=0;i<k;++i)
46     {
47         if(t&(1<<i))continue;
48         ret=min(ret,solve(i,t|(1<<i))+dis[arr[last]][i]);
49     }
50     return ret;
51 }
52 int main(void)
53 {
54     memset(dp,-1,sizeof(dp));
55     cin>>n>>m;
56     for(int i=0;i<m;++i)
57     {
58         int u,v;
59         cin>>u>>v;
60         e[u].push_back(v);
61         e[v].push_back(u);
62     }
63     cin>>k;
64     for(int i=0;i<k;++i)cin>>arr[i];
65     for(int i=0;i<k;++i)bfs(i);
66     for(int i=0;i<k;++i)
67     {
68         if(dis[arr[0]][i]==INF)
69         {
70             cout<<"-1"<<endl;
71             return 0;
72         }
73     }
74     int ans=INF;
75     for(int i=0;i<k;++i)
76     {
77         ans=min(ans,1+solve(i,(1<<i)));
78     }
79     cout<<ans<<endl;
80     return 0;
81 }

F:

给出0到N-1的一组排列,将排列向左移位k次,k=0,1,……,N-1,求每次移位后的排列的逆序对数。

分析:我们先算出刚开始的排列的逆序对数x0。每次移位相当于把第一个数放到末尾。对于第i次移位,假设第i-1次移位后的逆序对数为x,第一个数为a0,那么我们只需减去在第i-1次移位中a0的贡献P1,再加上在第i次移位中a0的贡献P2即可。由于这是0到N-1的排列,可以知道P1=a0(所有比他小的数),P2=N-1-a0(所有比他大的数),因此通过循环更新x0即可。

关于求逆序对,可以看一下这道题:https://www.luogu.com.cn/problem/P1908

 

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <vector>
 4 #include <algorithm>
 5 #include <queue>
 6 #include <vector>
 7 #include <map>
 8 #include <cstdlib>
 9 #include <cstring>
10 #include <cmath>
11 #include <set>
12 typedef long long ll;
13 const int INF=0x3f3f3f3f;
14 using namespace std;
15 int a[310000],b[310000],c[310000],n;
16 ll ans;
17 void msort(int h,int r)
18 {
19     if(h==r)return;
20     int mid=(h+r)/2,i=h,j=mid+1,k=h;
21     msort(h,mid);
22     msort(mid+1,r);
23     while(i<=mid&&j<=r)
24     {
25         if(a[i]<=a[j])
26         {
27             c[k++]=a[i++];
28         }
29         else
30         {
31             c[k++]=a[j++];
32             ans+=mid-i+1;
33         }
34     }
35     while(i<=mid)c[k++]=a[i++];
36     while(j<=r)c[k++]=a[j++];
37     for(int i=h;i<=r;++i)a[i]=c[i];
38 }
39 int main(void)
40 {
41     scanf("%d",&n);
42     for(int i=1;i<=n;++i)
43     {
44         scanf("%d",&a[i]);
45         b[i]=a[i];
46     }
47     msort(1,n);
48     cout<<ans<<endl;
49     for(int i=1;i<n;++i)
50     {
51         ans-=b[i];
52         ans+=n-1-b[i];
53         cout<<ans<<endl;
54     }
55     return 0;
56 }

 

posted @ 2021-01-31 08:52  yanying  阅读(133)  评论(0编辑  收藏  举报