题目链接: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 }
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 }
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 }