哈尔滨理工大学软件与微电子学院第八届程序设计竞赛同步赛(高年级) Solution

A:

Solved.

分别处理出每个%7后余数的数字个数,再组合一下

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3  
 4 #define ll long long
 5 int n, m;
 6 ll cnt[2][10];
 7  
 8 ll calc(ll x, ll y)
 9 {
10     if (x % 7 >= y) return x / 7 + 1; 
11     return x / 7;
12 }
13 
14 int main()
15 {
16     while (scanf("%d%d", &n, &m) != EOF)
17     {
18         memset(cnt, 0, sizeof cnt);
19         for (int i = 0; i < 7; ++i)
20         {
21             cnt[0][i] += calc(n, i);
22             cnt[1][i] += calc(m, i);
23         }
24         ll res = 0; 
25         --cnt[0][0], --cnt[1][0];
26         cnt[1][7] = cnt[1][0];
27         for (int i = 0; i < 7; ++i)
28             res += cnt[0][i] * cnt[1][7 - i];
29         printf("%lld\n", res);
30     }
31     return 0;
32 }
View Code

 

B:

Solved.

状压DP.

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3  
 4 #define ll long long
 5 int n,m;
 6 ll f[12][1<<11];
 7 bool ins[1<<11];
 8 int main(){
 9         while(cin>>n>>m&&n){
10                 for(int i=0;i<(1<<m);i++){
11                         bool cnt=0,hasodd=0;
12                         for(int j=0;j<m;j++)
13                                 if((i>>j)&1)hasodd|=cnt,cnt=0;
14                                 else  cnt^=1;
15                         ins[i]=hasodd|cnt?0:1;
16  
17                 }
18                 f[0][0]=1;
19                 for(int i=1;i<=n;i++)
20                         for(int j=0;j<(1<<m);j++){
21                                 f[i][j]=0;
22                                 for(int k=0;k<(1<<m);k++){
23                                         if((j&k)==0&&ins[j|k])
24                                                 f[i][j]+=f[i-1][k];
25                                 }
26                                  
27                         }
28                 cout<<f[n][0]<<endl;
29         }
30 }
View Code

 

C:

Solved.

 1 #include<bits/stdc++.h>
 2  
 3 using namespace std;
 4  
 5 int n, s;
 6  
 7 int main()
 8 {
 9     while(~scanf("%d %d", &n, &s))
10     {
11         int Min = 0x3f3f3f3f;
12         for(int i = 0; i < n; ++i)
13         {
14             int num = 0;
15             scanf("%d" , &num);
16             Min = min(Min, num);
17         }
18         printf("%d\n", s * Min);
19     }
20     return 0;
21 }
View Code

 

D:

Solved.

 1 #include<bits/stdc++.h>
 2  
 3 using namespace std;
 4  
 5 const int maxn = 1010;
 6 int n, s;
 7 int arr[maxn];
 8  
 9 int main()
10 {
11     while(~scanf("%d %d", &n, &s))
12     {
13         for(int i = 1; i <= n; ++i)
14         {
15             scanf("%d", arr + i);
16         }
17         sort(arr + 1, arr + 1 + n);
18         printf("%d\n", arr[n - 2] * s);
19     }
20     return 0;
21 }
View Code

 

E:

Solved.

最长公共子序列。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=1010;
 4 int f[maxn][maxn];
 5 char s1[maxn],s2[maxn];
 6 int main(){
 7     cin>>s1+1>>s2+1;
 8     int n=strlen(s1+1),m=strlen(s2+1);
 9     for(int i=1;i<=n;i++)
10     {
11          
12             for(int j=1;j<=m;j++)
13             {
14                     f[i][j]=max(f[i - 1][j], f[i][j - 1]);
15                     if(s1[i]==s2[j])
16                     {
17                         f[i][j]=max(f[i][j],f[i-1][j-1] + 1);
18                     }
19  
20             }
21     }
22     printf("%d\n",f[n][m]);
23 }
View Code

 

F:

Solved.

$dp[i][j][k] 表示到达i, j 的时候步数为k的方案数$

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int maxn=210;
 5 const ll MOD = 1e9 + 7;
 6 ll dp[maxn][maxn][maxn];
 7 int fx[8][2]={{1,2},{1,-2},{-1,2},{-1,-2},{2,1},{2,-1},{-2,1},{-2,-1}};
 8 int n,m,s;
 9 inline bool  check(int x,int y){
10         if(x<1 || x>n || y<1 ||y>m)return false;
11         return true;
12 }
13 int main(){
14     while(cin>>n>>m>>s)
15     {
16             memset(dp, 0, sizeof dp);
17         dp[1][1][0]=1;
18         for(int k=1;k<=s;k++)
19         {
20             for(int i=1;i<=n;i++)
21             {
22                 for(int j=1;j<=m;j++){
23                     for(int t=0;t<8;t++)
24                     {
25                         int x=i+fx[t][0];
26                         int y=j+fx[t][1];
27                         if(check(x,y)){
28                             dp[i][j][k]+=dp[x][y][k-1];
29                             dp[i][j][k]%=MOD;
30                         }
31                     }
32                 }
33             }
34         }
35         cout<<dp[n][m][s]<<endl;
36     }
37 }
View Code

 

G:

Unsolved.

 

H:

Solved.

考虑离线,对$每个数处理出到L左边离它最近的非互质的数,以及到R右边$离它最近的非互质的数,

再考虑先固定$l, 对每一个r处理出答案$

再考虑什么时候把数的贡献加进去,仅当这个数的$L < l 的时候便可以加入贡献,贡献的范围是[pos, R - 1], pos 表示那个数的位置$

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3  
  4 #define N 100010
  5 #define pii pair <int, int>
  6 int n, q, a[N], l[N], r[N], dp[N], ans[N], vis[N];
  7 vector <int> fac[N];
  8 vector <pii> v[N], qv[N];
  9  
 10 namespace SEG
 11 {
 12     int a[N << 2], lazy[N << 2];
 13     void build(int id, int l, int r)
 14     {
 15         a[id] = 0;
 16         if (l == r) return;
 17         int mid = (l + r) >> 1;
 18         build(id << 1, l, mid);
 19         build(id << 1 | 1, mid + 1, r);
 20     }
 21     void pushdown(int id, int l, int r, int mid)
 22     {
 23         if (!lazy[id]) return;
 24         lazy[id << 1] += lazy[id];
 25         a[id << 1] += lazy[id] * (mid - l + 1);
 26         lazy[id << 1 | 1] += lazy[id];
 27         a[id << 1 | 1] += lazy[id] * (r - mid);
 28         lazy[id] = 0;
 29     }
 30     void pushup(int id) { a[id] = a[id << 1] + a[id << 1 | 1]; }
 31     void update(int id, int l, int r, int ql, int qr, int val)
 32     {
 33         if (l >= ql && r <= qr)
 34         {
 35             a[id] += val * (r - l + 1);
 36             lazy[id] += val;
 37             return;
 38         }
 39         int mid = (l + r) >> 1;
 40         pushdown(id, l, r, mid);
 41         if (ql <= mid) update(id << 1, l, mid, ql, qr, val);
 42         if (qr > mid) update(id << 1 | 1, mid + 1, r, ql, qr, val);
 43         pushup(id);
 44     }
 45     int query(int id, int l, int r, int pos)
 46     {
 47         if (l == r) return a[id];
 48         int mid = (l + r) >> 1;
 49         pushdown(id, l, r, mid);
 50         if (pos <= mid) return query(id << 1, l, mid, pos);
 51         else return query(id << 1 | 1, mid + 1, r, pos);
 52     }
 53 }
 54  
 55 void init()
 56 {
 57     for (int i = 2; i <= 100000; ++i)
 58     {
 59         if (vis[i]) continue;
 60         fac[i].push_back(i);
 61         for (int j = 2 * i; j <= 100000; j += i)
 62         {
 63             vis[j] = 1;
 64             fac[j].push_back(i);
 65         }
 66     }
 67 }
 68  
 69 int main()
 70 {
 71     init();
 72     while (scanf("%d%d", &n, &q) != EOF)
 73     {
 74         for (int i = 0; i <= n + 1; ++i) l[i] = 0, r[i] = n + 1, v[i].clear(), qv[i].clear();
 75         for (int i = 1; i <= n; ++i) scanf("%d", a + i);
 76         memset(vis, 0, sizeof vis);
 77         for (int i = 1; i <= n; ++i)
 78             for (auto it : fac[a[i]])
 79                 l[i] = max(l[i], vis[it]), vis[it] = i;
 80         memset(vis, 0x3f, sizeof vis);
 81         for (int i = n; i >= 1; --i)
 82             for (auto it : fac[a[i]])
 83                 r[i] = min(r[i], vis[it]), vis[it] = i;
 84         //for (int i = 1; i <= n; ++i) printf("%d %d\n", l[i], r[i]);
 85         //for (int i = 1; i <= n; ++i) for (int j = 0, len = fac[a[i]].size(); j < len; ++j) printf("%d%c", fac[a[i]][j], " \n"[j == len - 1]);
 86         for (int i = 1; i <= n; ++i)
 87             v[l[i]].emplace_back(r[i], i);
 88         for (int qq = 1, l, r; qq <= q; ++qq)
 89         {
 90             scanf("%d%d", &l, &r);
 91             qv[l].emplace_back(r, qq);
 92         }
 93         SEG::build(1, 1, n);
 94         for (int i = 1; i <= n; ++i)
 95         {
 96             for (auto it : v[i - 1])
 97                 SEG::update(1, 1, n, it.second, it.first - 1, 1);
 98             for (auto it : qv[i])
 99                 ans[it.second] = SEG::query(1, 1, n, it.first);
100             SEG::update(1, 1, n, i, r[i] - 1, -1);
101         }
102         for (int i = 1; i <= q; ++i) printf("%d\n", ans[i]);
103     }
104     return 0;
105 }
View Code

 

I:

Solved.

特判$n == 0 并且 m == 0 的情况$

其他情况下,因为$k >= |n - m| 先手的人只需要去掉石子使得两堆相同,然后跟着另一个人取就可以必胜$

 1 #include<bits/stdc++.h>
 2  
 3 using namespace std;
 4  
 5 typedef long long ll;
 6  
 7 ll n, m, k;
 8  
 9 int main()
10 {
11     while(~scanf("%lld %lld %lld", &n, &m, &k))
12     {
13         if(n == 0 || m == 0) puts("LAOZI CHUI SI NI!");
14         else puts("HAI YOU SEI!");
15     }
16     return 0;
17 }
View Code

 

J:

Solved.

考虑 末尾两位为00, 25, 50, 75四种状态

  1 #include<bits/stdc++.h>
  2  
  3 using namespace std;
  4  
  5 const int INF = 0x3f3f3f3f;
  6 const int maxn = 1e5 + 10;
  7  
  8 char str[maxn];
  9  
 10 int main()
 11 {
 12     while(~scanf("%s", str + 1))
 13     {
 14         int ans = INF;
 15         int len = strlen(str + 1);
 16  
 17         //00
 18         int tmp1 = -1, tmp2 = -1;
 19         for(int i = len; i >= 1; --i)
 20         {
 21             if(str[i] == '0')
 22             {
 23                 if(tmp1 == -1) tmp1 = len - i;
 24                 else if(tmp2 == -1)
 25                 {
 26                     tmp2 = len - i - 1;
 27                     break;
 28                 }
 29             }
 30         }
 31         if(tmp1 != -1 && tmp2 != -1) ans = min(ans, tmp1 + tmp2);
 32  
 33         //25
 34         tmp1 = -1, tmp2 = -1;
 35         for(int i = len; i >= 1; --i)
 36         {
 37             if(str[i] == '5')
 38             {
 39                 if(tmp1 == -1) tmp1 = len - i;
 40             }
 41             if(str[i] == '2')
 42             {
 43                 if(tmp2 == -1) tmp2 = len - i;
 44             }
 45         }
 46  
 47         if(tmp1 != -1 && tmp2 != -1)
 48         {
 49             if(tmp1 < tmp2)
 50             {
 51                 ans = min(ans, tmp1 + tmp2 - 1);
 52             }
 53             else
 54             {
 55                 ans = min(ans, tmp1 + tmp2);
 56             }
 57         }
 58  
 59         //50
 60         tmp1 = -1, tmp2 = -1;
 61         for(int i = len; i >= 1; --i)
 62         {
 63             if(str[i] == '0')
 64             {
 65                 if(tmp1 == -1) tmp1 = len - i;
 66             }
 67             if(str[i] == '5')
 68             {
 69                 if(tmp2 == -1) tmp2 = len - i;
 70             }
 71         }
 72          
 73         if(tmp1 != -1 && tmp2 != -1)
 74         {
 75             if(tmp1 < tmp2)
 76             {
 77                 ans = min(ans, tmp1 + tmp2 - 1);
 78             }
 79             else
 80             {
 81                 ans = min(ans, tmp1 + tmp2);
 82             }
 83         }
 84         //75
 85         tmp1 = -1, tmp2 = -1;
 86         for(int i = len; i >= 1; --i)
 87         {
 88             if(str[i] == '5')
 89             {
 90                 if(tmp1 == -1) tmp1 = len - i;
 91             }
 92             if(str[i] == '7')
 93             {
 94                 if(tmp2 == -1) tmp2 = len - i;
 95             }
 96         }
 97         if(tmp1 != -1 && tmp2 != -1)
 98         {
 99             if(tmp1 < tmp2)
100             {
101                 ans = min(ans, tmp1 + tmp2 - 1);
102             }
103             else
104             {
105                 ans = min(ans, tmp1 + tmp2);
106             }
107         }
108         if(ans == INF) ans = -1;
109         printf("%d\n", ans);       
110     }
111     return 0;
112 }
View Code

 

posted @ 2018-12-01 18:43  Dup4  阅读(210)  评论(0编辑  收藏  举报