hihoCoder编程练习赛67
题目1 : 序列
描述
给定两个正整数 n, P,求满足以下两个条件的长度为 n 的序列 ai 个数:
1. 1 ≤ ai ≤ P
2. 不存在 1 ≤ l ≤ r ≤ n,满足al + al+1 + ... + ar 是 P 的倍数
由于方案数可能很大,你只需要输出方案数对 109+7 取模的值
输入
第一行两个正整数 n,P
1 ≤ n, P ≤ 104
输出
输出方案数对 109+7 取模的值
样例解释
满足条件的序列有两个:{1,1} 和 {2,2}
样例输入
2 3
样例输出
2
1 #include <iostream> 2 #define ll long long 3 4 using namespace std; 5 6 const ll MOD = 1000000007; 7 8 int main() 9 { 10 ll n, p; 11 while(cin>>n>>p){ 12 ll ans = 1; 13 p--; 14 while(n--){ 15 ans *= p; 16 ans %= MOD; 17 p--; 18 } 19 cout<<ans<<endl; 20 } 21 22 return 0; 23 }
题目2 : 彩球
描述
有一家商店,一共有 n × k 个彩球。球一共有 n 种颜色,每种颜色的球都是有恰好 k 个,现在你要从这 n×k 个球中选 n 个球,要求他们的颜色互不相同,求有几种选择的方案,由于方案数可能很大,你只需要输出方案数对 P 取模后的值。
输入
第一行三个正整数 n, k, P
对于50%的数据,有1 ≤ n, k, P ≤ 109
对于100%的数据,有1 ≤ n, k, P ≤ 1018
输出
输出方案数对 P 取模后的值
- 样例输入
-
2 2 100000
- 样例输出
-
4
1 def quick_pow(a, n, mod): 2 ans = 1 3 while(n!=0): 4 if(n%2==1): 5 ans = ans*a%mod 6 a = a*a%mod 7 n = n // 2 8 return ans 9 10 if __name__ == '__main__': 11 n, k, mod = raw_input().strip().split() 12 n = long(n) 13 k = long(k) 14 mod = long(mod) 15 print quick_pow(k, n, mod)
题目3 : 最优子段
描述
给定一个长度为 n 的序列 ai 和两个整数 A, B,要求你找一对数l, r,要求1 ≤ l ≤ r 且A×(ai+ai+1+...+ar)+B 最大
输入
第一行三个整数 n, A, B
第二行 n 个整数,第 i 个整数表示 ai
1 ≤ n ≤ 106
-106 ≤ A, B, ai ≤ 106
输出
输出最大的A×(ai+ai+1+...+ar)+B
样例解释
选择 (1,1) 或者 (4,4) 都可以
- 样例输入
-
4 2 3 0 -2 -2 0
- 样例输出
-
3
1 #include <iostream> 2 #define ll long long 3 4 using namespace std; 5 6 const int N = 1000010; 7 8 ll arr[N]; 9 10 ll dp(ll n){ 11 ll ans = 0; 12 ll sum = 0; 13 for(int i = 0; i <n; i++){ 14 sum += arr[i]; 15 ans = max(ans, sum); 16 if(sum < 0)sum = 0; 17 } 18 return ans; 19 } 20 21 int main() 22 { 23 ll n, A, B; 24 while(cin>>n>>A>>B){ 25 for(int i = 0; i < n; i++){ 26 cin>>arr[i]; 27 if(A<0)arr[i] *= -1; 28 } 29 if(A<0)cout<<-A*dp(n)+B<<endl; 30 else cout<<A*dp(n)+B<<endl; 31 } 32 33 return 0; 34 }
题目4 : 公路收费
描述
A 国有 n 个城市,第 i 个城市有 ai 个会议代表,这 n 个城市通过 n-$ 条双向的高速公路连接,保证每两个城市都可以通过高速公路互相到达,每个人通过一条高速公路都要付相应的费用。
现在 A 国的总统想挑选一个城市作为会议中心,要求全国所有会议代表都到这个城市来,为了方便大家出行,A 国的总统可以让不超过 k 条高速公路的收费变为 0 。
现在你要安排挑选的城市和免费的高速公路,最小化的所有会议代表的路费总和。
输入
第一行两个整数 n, k
第二行 n 个非负整数,第 i 个表示ai
接下来 n-1 行,每行三个整数 u, v, w,描述一条收费为 w 的高速公路 (u, v)
1 ≤ n ≤ 103
0 ≤ k ≤ n-1
1 ≤ w, ai≤ 105
输出
输出最小的路费总和
样例解释
让 (2,3) 免费,然后选 2 作为会议城市
- 样例输入
-
3 1 1 2 3 1 2 1 2 3 2
- 样例输出
-
1
1 #include <iostream> 2 #include <vector> 3 #include <cstring> 4 #include <algorithm> 5 6 #define ll long long 7 8 using namespace std; 9 10 const int N = 1010; 11 const ll INF = 0x3f3f3f3f3f3f3f3f; 12 13 ll arr[N], sum[N]; 14 15 struct Edge{ 16 int to, w, next; 17 }edges[2*N]; 18 int head[N], tot; 19 20 void init(){ 21 memset(head, -1, sizeof(head)); 22 tot = 0; 23 } 24 25 void add_edge(int u, int v, int w){ 26 edges[tot].to = v; 27 edges[tot].w = w; 28 edges[tot].next = head[u]; 29 head[u] = tot++; 30 } 31 32 vector<ll> vec; 33 int n, k; 34 35 void dfs(int u, int fa){ 36 sum[u] = arr[u]; 37 for(int i = head[u]; i != -1; i = edges[i].next){ 38 int v = edges[i].to; 39 int w = edges[i].w; 40 if(v != fa){ 41 dfs(v, u); 42 sum[u] += sum[v]; 43 vec.push_back(sum[v]*w); 44 } 45 } 46 } 47 48 ll work(int s){ 49 vec.clear(); 50 51 dfs(s, 0); 52 sort(vec.begin(), vec.end()); 53 ll ans = 0; 54 for(int i = 0; i < n-k-1; i++) 55 ans += vec[i]; 56 return ans; 57 } 58 59 int main() 60 { 61 while(cin>>n>>k){ 62 for(int i = 1; i <= n; i++) 63 cin>>arr[i]; 64 int u, v, w; 65 init(); 66 for(int i = 0; i < n-1; i++){ 67 cin>>u>>v>>w; 68 add_edge(u, v, w); 69 add_edge(v, u, w); 70 } 71 ll ans = INF; 72 for(int i = 1; i <= n; i++){ 73 ans = min(ans, work(i)); 74 } 75 cout<<ans<<endl; 76 } 77 return 0; 78 }