题目链接:https://vjudge.net/contest/149212#overview

  A题,水题,略过。

  B题,水题,读清题意即可。

  C题,数学题,如果把x表示成x=nb+m,则k=n/m属于[1,a],m属于[1,b-1]。然后由第一个式子得到n=(x-m)/b,那么带入第二个式子得,x=m(kb+1)。已经知道的m的范围,因此m的和为b(b-1)/2。然后因为k的范围已知,那么枚举k累和即可得到答案。注意m算好以后要先mod,不然太大了后面会溢出。代码如下:

 1 #include <stdio.h>
 2 #include <algorithm>
 3 #include <string.h>
 4 #include <map>
 5 #include <set>
 6 #include <vector>
 7 #include <queue>
 8 #include <iostream>
 9 using namespace std;
10 typedef long long ll;
11 typedef pair<int,int> pii;
12 const int N = 200000 + 5;
13 const int inf = 0x3f3f3f3f;
14 const int mod = 1e9 + 7;
15 
16 int main()
17 {
18     ll a,b;
19     cin >> a >> b;
20     ll m = b*(b-1)/2;
21     m %= mod;
22     ll ans = 0;
23     for(int k=1;k<=a;k++)
24     {
25         ll t = m*(k*b%mod + 1) % mod;
26         ans += t;
27         ans = (ans % mod + mod) % mod;
28         //ans += m*(k*b+1);
29     }
30     cout << ans << endl;
31     return 0;
32 }
C

 

  D题,状压DP,dp[i][j],i表示状态,j表示上一个被选的是哪一个菜。代码如下:

 1 #include <stdio.h>
 2 #include <algorithm>
 3 #include <string.h>
 4 #include <map>
 5 #include <set>
 6 #include <vector>
 7 #include <queue>
 8 #include <iostream>
 9 using namespace std;
10 typedef long long ll;
11 typedef pair<int,int> pii;
12 const int N = 200000 + 5;
13 const int inf = 0x3f3f3f3f;
14 const int mod = 1e9 + 7;
15 
16 int n,m,k;
17 int a[30];
18 map<pii,int> M;
19 ll ans;
20 bool vis[30];
21 ll dp[1<<20][20];
22 int get(int x)
23 {
24     int ans = 0;
25     while(x)
26     {
27         ans += x % 2;
28         x >>= 1;
29     }
30     return ans;
31 }
32 
33 int main()
34 {
35     cin >> n >> m >> k;
36     for(int i=1;i<=n;i++) scanf("%d",a+i);
37     for(int i=1;i<=k;i++)
38     {
39         int x,y,w;
40         scanf("%d%d%d",&x,&y,&w);
41         M[pii(x,y)] = w;
42     }
43     memset(dp,-1,sizeof dp);
44     for(int i=1;i<=n;i++) dp[1<<i-1][i] = a[i];
45     int all = (1 << n) - 1;
46     for(int mask=0;mask<=all;mask++)
47     {
48         int flag = get(mask) == m;
49         for(int i=1;i<=n;i++)
50         {
51             if(dp[mask][i] == -1) continue;
52             if(flag) ans = max(ans, dp[mask][i]);
53             for(int j=1;j<=n;j++)
54             {
55                 if(mask & (1<<j-1)) continue;
56                 dp[mask | (1<<j-1)][j] = max(dp[mask | (1<<j-1)][j], dp[mask][i] + M[pii(i,j)] + a[j]);
57             }
58         }
59     }
60     cout << ans << endl;
61     return 0;
62 }
D

 

  E题,lyf说什么dijkstra树,不知道什么东西。。题意有点问题,题目明明说不能有环结果第一个样例却有环。。看懂了题意以后这题不难。只要把距离相差1的点随便连即可。代码如下:

 1 #include <stdio.h>
 2 #include <algorithm>
 3 #include <string.h>
 4 #include <map>
 5 #include <set>
 6 #include <vector>
 7 #include <queue>
 8 #include <iostream>
 9 using namespace std;
10 typedef long long ll;
11 typedef pair<int,int> pii;
12 const int N = 100000 + 5;
13 const int inf = 0x3f3f3f3f;
14 const int mod = 1e9 + 7;
15 
16 int n,k;
17 struct node
18 {
19     int dis;
20     int id;
21     bool operator < (const node & temp) const
22     {
23         return dis < temp.dis;
24     }
25 }p[N];
26 vector<int> v[N];
27 vector<pii> ans;
28 
29 int main()
30 {
31     cin >> n >> k;
32     for(int i=1;i<=n;i++)
33     {
34         scanf("%d",&p[i].dis);
35         p[i].id = i;
36         v[p[i].dis].push_back(i);
37     }
38     sort(p+1,p+1+n);
39     int max_dis = p[n].dis;
40     if(v[0].size() != 1) return 0*puts("-1");
41     int flag = 1;
42     for(int i=1;i<=max_dis;i++)
43     {
44         if(i == 1)
45         {
46             if(v[1].size() > k)
47             {
48                 flag = 0;
49                 break;
50             }
51             for(int j=0;j<v[1].size();j++) ans.push_back(pii(v[0][0], v[1][j]));
52         }
53         else
54         {
55             if((ll)(k-1)*v[i-1].size() < v[i].size())
56             {
57                 flag = 0;
58                 break;
59             }
60             int pos = 0;
61             for(int j=0;j<v[i].size();j++)
62             {
63                 pos++;
64                 if(pos > v[i-1].size()) pos = 1;
65                 ans.push_back(pii(v[i-1][pos-1], v[i][j]));
66             }
67         }
68     }
69     if(flag == 0) puts("-1");
70     else
71     {
72         printf("%d\n",ans.size());
73         for(int i=0;i<ans.size();i++) printf("%d %d\n",ans[i].first, ans[i].second);
74     }
75     return 0;
76 }
E