div.2
给定一个偶数n(<=100),把价值为1~n^2的糖们分发给n个小朋友,使得大家手上糖的总价值一样。
考虑这样配对:(1,n^2),(2,n^2-1),(3,n^2-2)...(i,n^2-i+1)。每对价值和都是n^2+1,总共有n^2/2对,按对分给小朋友就好啦。
1 #include <stdio.h> 2 3 int main() { 4 int n; 5 scanf("%d",&n); 6 for (int i = 0,l = 1,r = n * n; i < n; ++ i) { 7 for (int j = 0; j < n / 2; ++ j) { 8 if (j) { 9 putchar(‘ ‘); 10 } 11 printf("%d %d",l,r); 12 l ++; 13 r --; 14 } 15 puts(""); 16 } 17 }
div.1
CodeForces 510D Fox And Jumping
事实上题意等价于找到一组费用和最小的卡们,使得 ∑Li*Xi = 1。其中Xi为任意整数。
然后大家知道对于一个方程ax+by=c,有整数解当且仅当gcd(a,b)整除c。(不知道的话可以去学习一下扩展欧几里得算法)。
所以这里从两个未知数推广一下,就是找到一组费用和最小的卡们,使得gcd(Li) = 1。
所以dp(i,j)表示前i个数,当前gcd值为j,的最小费用和。j的范围虽然有1e9但是数量至多nlog(A)^2个,所以离散化一下即可。其中A为数值大小。
时间复杂度O(n^2 * log(A)^2 * log(log(A)^2))。
1 #include <bits/stdc++.h> 2 typedef long long LL; 3 4 const int N = 300 + 5; 5 const int INF = 0x3f3f3f3f; 6 int n,L[N],C[N]; 7 std::vector<int> values; 8 std::vector<int> dp; 9 10 int get(int x) { 11 return std::lower_bound(values.begin(),values.end(),x) 12 - values.begin(); 13 } 14 15 void decompose(int x) { 16 for (int i = 1; i*i <= x; ++ i) { 17 if (x % i == 0) { 18 values.push_back(i); 19 values.push_back(x/i); 20 } 21 } 22 } 23 24 int gcd(int a,int b) { 25 return b == 0 ? a : gcd(b,a%b); 26 } 27 28 inline void toMin(int &a,int b) { 29 if (a > b) a = b; 30 } 31 32 int main() { 33 scanf("%d",&n); 34 for (int i = 0; i < n; ++ i) { 35 scanf("%d",L+i); 36 decompose(L[i]); 37 } 38 for (int i = 0; i < n; ++ i) { 39 scanf("%d",C+i); 40 } 41 std::sort(values.begin(),values.end()); 42 values.erase(std::unique(values.begin(),values.end()),values.end()); 43 dp.resize(values.size(),INF); 44 for (int i = 0; i < n; ++ i) { 45 int p = get(L[i]); 46 toMin(dp[p],C[i]); 47 for (int j = 0; j < dp.size(); ++ j) { 48 if (dp[j] != INF) { 49 toMin(dp[get(gcd(values[j],L[i]))],C[i]+dp[j]); 50 } 51 } 52 } 53 int answer = dp[0]; 54 if (answer == INF) 55 answer = -1; 56 printf("%d\n",answer); 57 return 0; 58 }
时间: 2024-10-12 13:59:39