ACdream Andrew Stankevich's Contest(1)

【来源】http://blog.csdn.net/houserabbit/article/details/39719063

A:

高精度模拟即可  与n互素的数不会离n/2太远  直接暴力

代码:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #include<stdio.h>  
  2. #include<string>  
  3. #include<string.h>  
  4. #include<iostream>  
  5. using namespace std;  
  6.    
  7. //compare比较函数:相等返回0,大于返回1,小于返回-1  
  8. int compare(string str1, string str2) {  
  9.     if (str1.length() > str2.length())  
  10.         return 1;  
  11.     else if (str1.length() < str2.length())  
  12.         return -1;  
  13.     else  
  14.         return str1.compare(str2);  
  15. }  
  16. //高精度加法  
  17. //只能是两个正数相加  
  18. string add(string str1, string str2) //高精度加法  
  19.         {  
  20.     string str;  
  21.    
  22.     int len1 = str1.length();  
  23.     int len2 = str2.length();  
  24.     //前面补0,弄成长度相同  
  25.     if (len1 < len2) {  
  26.         for (int i = 1; i <= len2 - len1; i++)  
  27.             str1 = "0" + str1;  
  28.     } else {  
  29.         for (int i = 1; i <= len1 - len2; i++)  
  30.             str2 = "0" + str2;  
  31.     }  
  32.     len1 = str1.length();  
  33.     int cf = 0;  
  34.     int temp;  
  35.     for (int i = len1 - 1; i >= 0; i--) {  
  36.         temp = str1[i] - '0' + str2[i] - '0' + cf;  
  37.         cf = temp / 10;  
  38.         temp %= 10;  
  39.         str = char(temp + '0') + str;  
  40.     }  
  41.     if (cf != 0)  
  42.         str = char(cf + '0') + str;  
  43.     return str;  
  44. }  
  45. //高精度减法  
  46. //只能是两个正数相减,而且要大减小  
  47. string sub(string str1, string str2) //高精度减法  
  48.         {  
  49.     string str;  
  50.     int tmp = str1.length() - str2.length();  
  51.     int cf = 0;  
  52.     for (int i = str2.length() - 1; i >= 0; i--) {  
  53.         if (str1[tmp + i] < str2[i] + cf) {  
  54.             str = char(str1[tmp + i] - str2[i] - cf + '0' + 10) + str;  
  55.             cf = 1;  
  56.         } else {  
  57.             str = char(str1[tmp + i] - str2[i] - cf + '0') + str;  
  58.             cf = 0;  
  59.         }  
  60.     }  
  61.     for (int i = tmp - 1; i >= 0; i--) {  
  62.         if (str1[i] - cf >= '0') {  
  63.             str = char(str1[i] - cf) + str;  
  64.             cf = 0;  
  65.         } else {  
  66.             str = char(str1[i] - cf + 10) + str;  
  67.             cf = 1;  
  68.         }  
  69.     }  
  70.     str.erase(0, str.find_first_not_of('0')); //去除结果中多余的前导0  
  71.     return str;  
  72. }  
  73. //高精度乘法  
  74. //只能是两个正数相乘  
  75. string mul(string str1, string str2) {  
  76.     string str;  
  77.     int len1 = str1.length();  
  78.     int len2 = str2.length();  
  79.     string tempstr;  
  80.     for (int i = len2 - 1; i >= 0; i--) {  
  81.         tempstr = "";  
  82.         int temp = str2[i] - '0';  
  83.         int t = 0;  
  84.         int cf = 0;  
  85.         if (temp != 0) {  
  86.             for (int j = 1; j <= len2 - 1 - i; j++)  
  87.                 tempstr += "0";  
  88.             for (int j = len1 - 1; j >= 0; j--) {  
  89.                 t = (temp * (str1[j] - '0') + cf) % 10;  
  90.                 cf = (temp * (str1[j] - '0') + cf) / 10;  
  91.                 tempstr = char(t + '0') + tempstr;  
  92.             }  
  93.             if (cf != 0)  
  94.                 tempstr = char(cf + '0') + tempstr;  
  95.         }  
  96.         str = add(str, tempstr);  
  97.     }  
  98.     str.erase(0, str.find_first_not_of('0'));  
  99.     return str;  
  100. }  
  101.    
  102. //高精度除法  
  103. //两个正数相除,商为quotient,余数为residue  
  104. //需要高精度减法和乘法  
  105. void div(string str1, string str2, string "ient, string &residue) {  
  106.     quotient = residue = ""//清空  
  107.     if (str2 == "0"//判断除数是否为0  
  108.             {  
  109.         quotient = residue = "ERROR";  
  110.         return;  
  111.     }  
  112.     if (str1 == "0"//判断被除数是否为0  
  113.             {  
  114.         quotient = residue = "0";  
  115.         return;  
  116.     }  
  117.     int res = compare(str1, str2);  
  118.     if (res < 0) {  
  119.         quotient = "0";  
  120.         residue = str1;  
  121.         return;  
  122.     } else if (res == 0) {  
  123.         quotient = "1";  
  124.         residue = "0";  
  125.         return;  
  126.     } else {  
  127.         int len1 = str1.length();  
  128.         int len2 = str2.length();  
  129.         string tempstr;  
  130.         tempstr.append(str1, 0, len2 - 1);  
  131.         for (int i = len2 - 1; i < len1; i++) {  
  132.             tempstr = tempstr + str1[i];  
  133.             tempstr.erase(0, tempstr.find_first_not_of('0'));  
  134.             if (tempstr.empty())  
  135.                 tempstr = "0";  
  136.             for (char ch = '9'; ch >= '0'; ch--) //试商  
  137.                     {  
  138.                 string str, tmp;  
  139.                 str = str + ch;  
  140.                 tmp = mul(str2, str);  
  141.                 if (compare(tmp, tempstr) <= 0) //试商成功  
  142.                         {  
  143.                     quotient = quotient + ch;  
  144.                     tempstr = sub(tempstr, tmp);  
  145.                     break;  
  146.                 }  
  147.             }  
  148.         }  
  149.         residue = tempstr;  
  150.     }  
  151.     quotient.erase(0, quotient.find_first_not_of('0'));  
  152.     if (quotient.empty())  
  153.         quotient = "0";  
  154. }  
  155.    
  156. string gcd(string a, string b) {  
  157.     if (b.empty())  
  158.         return a;  
  159.     string s, y;  
  160.     div(a, b, s, y);  
  161.     //cout<<a<<" "<<b<<" "<<s<<" "<<y<<endl;  
  162.     return gcd(b, y);  
  163. }  
  164.    
  165. int main() {  
  166.     ios::sync_with_stdio(false);  
  167.     string n, f1, f2;  
  168.     while (cin >> n) {  
  169.         div(n, "2", f1, f2);  
  170.         while (1) {  
  171.             if (gcd(n, f1) == "1")  
  172.                 break;  
  173.             f1 = sub(f1, "1");  
  174.         }  
  175.         cout << f1 << endl;  
  176.     }  
  177.     return 0;  
  178. }  

B:

上下界无源无汇网络流  不能再模版了…

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #include<cstdio>  
  2. #include<iostream>  
  3. #include<cstring>  
  4. #include<string>  
  5. #include<algorithm>  
  6. #include<cmath>  
  7. #include<cassert>  
  8. #include<vector>  
  9. #include<set>  
  10. #include<map>  
  11. #include<queue>  
  12. using namespace std;  
  13. const int MAX = 100005;  
  14. const int INF = 1000000000;  
  15.    
  16. struct EDGE {  
  17.     int v, c, next;  
  18. } edge[1000000];  
  19. int E, head[MAX];  
  20. int gap[MAX], cur[MAX];  
  21. int pre[MAX], dis[MAX];  
  22. int in[225], low[50000];  
  23.    
  24. void add_edge(int s, int t, int c, int cc) {  
  25.     edge[E].v = t;  
  26.     edge[E].c = c;  
  27.     edge[E].next = head[s];  
  28.     head[s] = E++;  
  29.     edge[E].v = s;  
  30.     edge[E].c = cc;  
  31.     edge[E].next = head[t];  
  32.     head[t] = E++;  
  33. }  
  34.    
  35. int min(int a, int b) {  
  36.     return (a == -1 || b < a) ? b : a;  
  37. }  
  38.    
  39. int SAP(int s, int t, int n) {  
  40.     memset(gap, 0, sizeof(gap));  
  41.     memset(dis, 0, sizeof(dis));  
  42.     int i;  
  43.     for (i = 0; i < n; i++)  
  44.         cur[i] = head[i];  
  45.     int u = pre[s] = s, maxflow = 0, aug = -1, v;  
  46.     gap[0] = n;  
  47.     while (dis[s] < n) {  
  48.         loop: for (i = cur[u]; i != -1; i = edge[i].next) {  
  49.             v = edge[i].v;  
  50.             if (edge[i].c > 0 && dis[u] == dis[v] + 1) {  
  51.                 aug = min(aug, edge[i].c);  
  52.                 pre[v] = u;  
  53.                 cur[u] = i;  
  54.                 u = v;  
  55.                 if (u == t) {  
  56.                     for (u = pre[u]; v != s; v = u, u = pre[u]) {  
  57.                         edge[cur[u]].c -= aug;  
  58.                         edge[cur[u] ^ 1].c += aug;  
  59.                     }  
  60.                     maxflow += aug;  
  61.                     aug = -1;  
  62.                 }  
  63.                 goto loop;  
  64.             }  
  65.         }  
  66.         int mindis = n;  
  67.         for (i = head[u]; i != -1; i = edge[i].next) {  
  68.             v = edge[i].v;  
  69.             if (edge[i].c > 0 && dis[v] < mindis) {  
  70.                 cur[u] = i;  
  71.                 mindis = dis[v];  
  72.             }  
  73.         }  
  74.         if ((--gap[dis[u]]) == 0)  
  75.             break;  
  76.         gap[dis[u] = mindis + 1]++;  
  77.         u = pre[u];  
  78.     }  
  79.     return maxflow;  
  80. }  
  81.    
  82. bool solve(int n) {  
  83.     for (int i = 1; i <= n; i++) {  
  84.         if (in[i] > 0)  
  85.             add_edge(0, i, in[i], 0);  
  86.         if (in[i] < 0)  
  87.             add_edge(i, n + 1, -in[i], 0);  
  88.     }  
  89.     SAP(0, n + 1, n + 2);  
  90.     for (int i = head[0]; i != -1; i = edge[i].next) //从源点出发的边都满流  
  91.             {  
  92.         if (edge[i].c)  
  93.             return false;  
  94.     }  
  95.     return true;  
  96. }  
  97.    
  98. int main() {  
  99.     int n, m, a, b, c;  
  100.     while (~scanf("%d%d", &n, &m)) {  
  101.         E = 0;  
  102.         memset(head, -1, sizeof(head));  
  103.         memset(in, 0, sizeof(in));  
  104.         for (int i = 0; i < m; i++) {  
  105.             scanf("%d%d%d%d", &a, &b, &low[i], &c);  
  106.             in[a] -= low[i], in[b] += low[i];  
  107.             add_edge(a, b, c - low[i], 0);  
  108.         }  
  109.         if (solve(n)) {  
  110.             printf("YES\n");  
  111.             for (int i = 0; i < m; i++)  
  112.                 printf("%d\n", edge[(i << 1) ^ 1].c + low[i]); //反向的流即自由流,再加上下界的流  
  113.         } else  
  114.             printf("NO\n");  
  115.     }  
  116.     return 0;  
  117. }  

C:

题可以转化为树上选尽量多的边  选出的边之间没有公共点

树形dp可解

我用dp[i][0.1]表示i这个点的子树的最大值  1表示i点与子树中的点匹配了  0表示没有  我用dp[i][2]表示dp[i][0.1]中的大者  那么转移方程可以很容易的写出

dp[i][0] = sum(dp[v][2]) 其中v表示i的儿子  dp[i][1] = sum(dp[v][2]) - dp[v][2] + dp[v][0] + 1那么这时i和v匹配了

dp的同时记录匹配是很容易的  然后倒着推回去  就可以打印方案了

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #include<cstdio>  
  2. #include<iostream>  
  3. #include<cstring>  
  4. #include<string>  
  5. #include<algorithm>  
  6. #include<map>  
  7. #include<set>  
  8. #include<vector>  
  9. #include<queue>  
  10. #include<cstdlib>  
  11. #include<ctime>  
  12. #include<cmath>  
  13. using namespace std;  
  14. #define N 500010  
  15. #define mp(x,y) make_pair(x,y)  
  16.    
  17. int n;  
  18. int dp[N][3], pre[N], ans[N];  
  19. int head[N], tot;  
  20. struct edge {  
  21.     int v, next;  
  22. } ed[N];  
  23. int qu[N];  
  24. pair<intint> que[N];  
  25.    
  26. void add(int u, int v) {  
  27.     ed[tot].v = v;  
  28.     ed[tot].next = head[u];  
  29.     head[u] = tot++;  
  30. }  
  31.    
  32. void bfs() {  
  33.     int l = 1, r = 2, u, i;  
  34.     qu[1] = 1;  
  35.     while (l < r) {  
  36.         u = qu[l++];  
  37.         for (i = head[u]; ~i; i = ed[i].next)  
  38.             qu[r++] = ed[i].v;  
  39.     }  
  40. }  
  41.    
  42. int main() {  
  43.     int i, j, k, tmp;  
  44.     while (~scanf("%d", &n)) {  
  45.         tot = 0;  
  46.         memset(head, -1, sizeof(head));  
  47.         memset(dp, 0, sizeof(dp));  
  48.         memset(pre, 0, sizeof(pre));  
  49.         memset(ans, 0, sizeof(ans));  
  50.         for (i = 2; i <= n; i++) {  
  51.             scanf("%d", &j);  
  52.             add(j, i);  
  53.         }  
  54.         bfs();  
  55.         for (i = n; i >= 1; i--) {  
  56.             k = 0;  
  57.             for (j = head[i]; ~j; j = ed[j].next)  
  58.                 k += dp[ed[j].v][2];  
  59.             dp[i][0] = k;  
  60.             for (j = head[i]; ~j; j = ed[j].next) {  
  61.                 int v = ed[j].v;  
  62.                 tmp = k - dp[v][2] + dp[v][0] + 1;  
  63.                 if (tmp > dp[i][1]) {  
  64.                     pre[i] = v;  
  65.                     dp[i][1] = tmp;  
  66.                 }  
  67.             }  
  68.             dp[i][2] = max(dp[i][0], dp[i][1]);  
  69.         }  
  70.         printf("%d\n", dp[1][2] * 1000);  
  71.         int l = 1, r = 2;  
  72.         pair<intint> u, v;  
  73.         if (dp[1][2] == dp[1][1])  
  74.             que[1] = mp(1,1);  
  75.         else  
  76.             que[1] = mp(1,0);  
  77.         while (l < r) {  
  78.             u = que[l++];  
  79.             for (i = head[u.first]; ~i; i = ed[i].next) {  
  80.                 v.first = ed[i].v;  
  81.                 if (v.first == pre[u.first] && u.second)  
  82.                     v.second = 0;  
  83.                 else {  
  84.                     if (dp[v.first][2] == dp[v.first][0])  
  85.                         v.second = 0;  
  86.                     else  
  87.                         v.second = 1;  
  88.                 }  
  89.                 que[r++] = v;  
  90.             }  
  91.             if (u.second)  
  92.                 ans[pre[u.first]] = 1;  
  93.         }  
  94.         for (i = j = 1; i <= n; i++) {  
  95.             if (ans[i]) {  
  96.                 if (j)  
  97.                     j = 0;  
  98.                 else  
  99.                     printf(" ");  
  100.                 printf("%d", i);  
  101.             }  
  102.         }  
  103.         printf("\n");  
  104.         return 0;  
  105.     }  
  106. }  

D:

我不知道什么题  队友说先记个数然后求个和…  反正我就这么写了- -b

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #include<cstdio>  
  2. #include<iostream>  
  3. #include<cstring>  
  4. #include<string>  
  5. #include<algorithm>  
  6. #include<map>  
  7. #include<set>  
  8. #include<vector>  
  9. #include<queue>  
  10. #include<cstdlib>  
  11. #include<ctime>  
  12. #include<cmath>  
  13. using namespace std;  
  14. typedef long long LL;  
  15. #define inf ((1U<<31)-1)  
  16. #define N 10010  
  17.    
  18. int n, m;  
  19. LL ans;  
  20. int x[N];  
  21.    
  22. int main() {  
  23.     int i, u, v;  
  24.     while (~scanf("%d%d", &n, &m)) {  
  25.         memset(x, 0, sizeof(x));  
  26.         ans = 0;  
  27.         for (i = 1; i <= m; i++) {  
  28.             scanf("%d%d", &u, &v);  
  29.             x[u]++;  
  30.             x[v]++;  
  31.         }  
  32.         for (i = 1; i <= n; i++)  
  33.             ans += (LL) (x[i]) * x[i];  
  34.         printf("%lld\n", ans);  
  35.     }  
  36.     return 0;  
  37. }  

E:

一开始以为这题是找循环节  后来发现循环节可能不存在

m很小  所以我们可以利用状压打表  这样形成了一个矩阵  矩阵中(i,j)=1表示能从i状态转到j状态  我们发现这个矩阵是始终不变的  换句话说就是初始状态根据这个矩阵做n次操作  这种事明显可以快速幂来搞  正好前面写过高精度  拿来直接改  1A神马的还是稳稳地 ~~

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #include<cstdio>  
  2. #include<iostream>  
  3. #include<cstring>  
  4. #include<string>  
  5. #include<algorithm>  
  6. #include<map>  
  7. #include<set>  
  8. #include<vector>  
  9. #include<queue>  
  10. #include<cstdlib>  
  11. #include<ctime>  
  12. #include<cmath>  
  13. using namespace std;  
  14.    
  15. string n;  
  16. int m, p;  
  17. int k[32][32];  
  18. int bin[10];  
  19.    
  20. //高精度  
  21. //compare比较函数:相等返回0,大于返回1,小于返回-1  
  22. int compare(string str1, string str2) {  
  23.     if (str1.length() > str2.length())  
  24.         return 1;  
  25.     else if (str1.length() < str2.length())  
  26.         return -1;  
  27.     else  
  28.         return str1.compare(str2);  
  29. }  
  30. //高精度加法  
  31. //只能是两个正数相加  
  32. string add(string str1, string str2) //高精度加法  
  33.         {  
  34.     string str;  
  35.    
  36.     int len1 = str1.length();  
  37.     int len2 = str2.length();  
  38.     //前面补0,弄成长度相同  
  39.     if (len1 < len2) {  
  40.         for (int i = 1; i <= len2 - len1; i++)  
  41.             str1 = "0" + str1;  
  42.     } else {  
  43.         for (int i = 1; i <= len1 - len2; i++)  
  44.             str2 = "0" + str2;  
  45.     }  
  46.     len1 = str1.length();  
  47.     int cf = 0;  
  48.     int temp;  
  49.     for (int i = len1 - 1; i >= 0; i--) {  
  50.         temp = str1[i] - '0' + str2[i] - '0' + cf;  
  51.         cf = temp / 10;  
  52.         temp %= 10;  
  53.         str = char(temp + '0') + str;  
  54.     }  
  55.     if (cf != 0)  
  56.         str = char(cf + '0') + str;  
  57.     return str;  
  58. }  
  59. //高精度减法  
  60. //只能是两个正数相减,而且要大减小  
  61. string sub(string str1, string str2) //高精度减法  
  62.         {  
  63.     string str;  
  64.     int tmp = str1.length() - str2.length();  
  65.     int cf = 0;  
  66.     for (int i = str2.length() - 1; i >= 0; i--) {  
  67.         if (str1[tmp + i] < str2[i] + cf) {  
  68.             str = char(str1[tmp + i] - str2[i] - cf + '0' + 10) + str;  
  69.             cf = 1;  
  70.         } else {  
  71.             str = char(str1[tmp + i] - str2[i] - cf + '0') + str;  
  72.             cf = 0;  
  73.         }  
  74.     }  
  75.     for (int i = tmp - 1; i >= 0; i--) {  
  76.         if (str1[i] - cf >= '0') {  
  77.             str = char(str1[i] - cf) + str;  
  78.             cf = 0;  
  79.         } else {  
  80.             str = char(str1[i] - cf + 10) + str;  
  81.             cf = 1;  
  82.         }  
  83.     }  
  84.     str.erase(0, str.find_first_not_of('0')); //去除结果中多余的前导0  
  85.     return str;  
  86. }  
  87. //高精度乘法  
  88. //只能是两个正数相乘  
  89. string mul(string str1, string str2) {  
  90.     string str;  
  91.     int len1 = str1.length();  
  92.     int len2 = str2.length();  
  93.     string tempstr;  
  94.     for (int i = len2 - 1; i >= 0; i--) {  
  95.         tempstr = "";  
  96.         int temp = str2[i] - '0';  
  97.         int t = 0;  
  98.         int cf = 0;  
  99.         if (temp != 0) {  
  100.             for (int j = 1; j <= len2 - 1 - i; j++)  
  101.                 tempstr += "0";  
  102.             for (int j = len1 - 1; j >= 0; j--) {  
  103.                 t = (temp * (str1[j] - '0') + cf) % 10;  
  104.                 cf = (temp * (str1[j] - '0') + cf) / 10;  
  105.                 tempstr = char(t + '0') + tempstr;  
  106.             }  
  107.             if (cf != 0)  
  108.                 tempstr = char(cf + '0') + tempstr;  
  109.         }  
  110.         str = add(str, tempstr);  
  111.     }  
  112.     str.erase(0, str.find_first_not_of('0'));  
  113.     return str;  
  114. }  
  115.    
  116. //高精度除法  
  117. //两个正数相除,商为quotient,余数为residue  
  118. //需要高精度减法和乘法  
  119. void div(string str1, string str2, string "ient, string &residue) {  
  120.     quotient = residue = ""//清空  
  121.     if (str2 == "0"//判断除数是否为0  
  122.             {  
  123.         quotient = residue = "ERROR";  
  124.         return;  
  125.     }  
  126.     if (str1 == "0"//判断被除数是否为0  
  127.             {  
  128.         quotient = residue = "0";  
  129.         return;  
  130.     }  
  131.     int res = compare(str1, str2);  
  132.     if (res < 0) {  
  133.         quotient = "0";  
  134.         residue = str1;  
  135.         return;  
  136.     } else if (res == 0) {  
  137.         quotient = "1";  
  138.         residue = "0";  
  139.         return;  
  140.     } else {  
  141.         int len1 = str1.length();  
  142.         int len2 = str2.length();  
  143.         string tempstr;  
  144.         tempstr.append(str1, 0, len2 - 1);  
  145.         for (int i = len2 - 1; i < len1; i++) {  
  146.             tempstr = tempstr + str1[i];  
  147.             tempstr.erase(0, tempstr.find_first_not_of('0'));  
  148.             if (tempstr.empty())  
  149.                 tempstr = "0";  
  150.             for (char ch = '9'; ch >= '0'; ch--) //试商  
  151.                     {  
  152.                 string str, tmp;  
  153.                 str = str + ch;  
  154.                 tmp = mul(str2, str);  
  155.                 if (compare(tmp, tempstr) <= 0) //试商成功  
  156.                         {  
  157.                     quotient = quotient + ch;  
  158.                     tempstr = sub(tempstr, tmp);  
  159.                     break;  
  160.                 }  
  161.             }  
  162.         }  
  163.         residue = tempstr;  
  164.     }  
  165.     quotient.erase(0, quotient.find_first_not_of('0'));  
  166.     if (quotient.empty())  
  167.         quotient = "0";  
  168. }  
  169.    
  170. //快速幂  
  171. const int mat_n = 32;  
  172. void matrix_mul(int a[][mat_n], int b[][mat_n]) {  
  173.     int c[mat_n][mat_n];  
  174.     int i, j, k;  
  175.     for (i = 0; i < mat_n; i++) {  
  176.         for (j = 0; j < mat_n; j++) {  
  177.             c[i][j] = 0;  
  178.             for (k = 0; k < mat_n; k++) {  
  179.                 c[i][j] = (c[i][j] + (a[i][k] * b[k][j]) % p) % p;  
  180.             }  
  181.         }  
  182.     }  
  183.     for (i = 0; i < mat_n; i++)  
  184.         for (j = 0; j < mat_n; j++)  
  185.             a[i][j] = c[i][j];  
  186. }  
  187.    
  188. void matrix_power(int s[][mat_n]) {  
  189.     int ans[mat_n][mat_n];  
  190.     memset(ans, 0, sizeof(ans));  
  191.     int i, j;  
  192.     for (i = 0; i < mat_n; i++)  
  193.         ans[i][i] = 1;  
  194.     string sh, yu;  
  195.     while (compare(n, "0") != 0) {  
  196.         div(n, "2", sh, yu);  
  197.         if (yu == "1")  
  198.             matrix_mul(ans, s);  
  199.         n = sh;  
  200.         matrix_mul(s, s);  
  201.     }  
  202.    
  203.     for (i = 0; i < mat_n; i++)  
  204.         for (j = 0; j < mat_n; j++)  
  205.             s[i][j] = ans[i][j];  
  206. }  
  207.    
  208. int main() {  
  209.     ios::sync_with_stdio(false);  
  210.     int i, j, f, flag;  
  211.     bin[0] = 1;  
  212.     for (f = 1; f < 10; f++)  
  213.         bin[f] = bin[f - 1] << 1;  
  214.     while (cin >> n >> m >> p) {  
  215.         for (i = 0; i < bin[m]; i++) {  
  216.             for (j = 0; j < bin[m]; j++) {  
  217.                 flag = 1;  
  218.                 for (f = 0; f < m - 1; f++) {  
  219.                     if (((i & bin[f]) == (j & bin[f])  
  220.                             && (i & bin[f + 1]) == (j & bin[f + 1])  
  221.                             && ((i & bin[f]) << 1) == (j & bin[f + 1]))) {  
  222.                         flag = 0;  
  223.                         break;  
  224.                     }  
  225.                 }  
  226.                 k[i][j] = flag;  
  227.                 //printf("%d ", flag);  
  228.             }  
  229.             //printf("\n");  
  230.         }  
  231.         n = sub(n, "1");  
  232.         matrix_power(k);  
  233.         f = 0;  
  234.         for (i = 0; i < bin[m]; i++) {  
  235.             for (j = 0; j < bin[m]; j++)  
  236.                 f += k[i][j];  
  237.         }  
  238.         printf("%d\n", f % p);  
  239.     }  
  240.     return 0;  
  241. }  

F:

唯一一道没做出的题  题解看这http://www.cppblog.com/Yuan/archive/2010/05/02/114163.html

当时我们的思路就卡在“将视角当作边权”这里  这个想法很是巧妙


G:

我犯二的题  我一开始想  按照不讨厌来建边  然后最大团就是答案  但是点这么多…  这时队友说  “简单的二维不降子序列题”…  这才顿悟…  不讨厌就是S和B都大  那么不就是标准的模型了…

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #include<iostream>  
  2. #include<cstdio>  
  3. #include<cstring>  
  4. #include<algorithm>  
  5. using namespace std;  
  6.    
  7. int dp[100010],mark[100010],cnt[100010];  
  8. const int inf=1e9;  
  9.    
  10. struct node{  
  11.     int x,y,idx;  
  12.     bool operator < (const node &a) const{  
  13.         return x<a.x||(x==a.x&&y>a.y);  
  14.     }  
  15. }p[100010];  
  16.    
  17. int main()  
  18. {  
  19.     int n,t,x,y,ans;  
  20.     int i;  
  21.     while(scanf("%d",&n)!=EOF)  
  22.     {  
  23.         ans=0;  
  24.         //printf("n.%d\n",n);  
  25.         for(i=0;i<n;i++){  
  26.             scanf("%d%d",&x,&y);  
  27.             //printf("u.........%d\n",i);  
  28.             p[i].x=x;  
  29.             p[i].y=y;  
  30.             p[i].idx=i+1;  
  31.         }  
  32.         sort(p,p+n);  
  33.         for(i=0;i<n;i++) dp[i]=inf;  
  34.         for(i=0;i<n;i++){  
  35.             int tmp=lower_bound(dp,dp+n,p[i].y)-dp;  
  36.             dp[tmp]=p[i].y;  
  37.             mark[i]=tmp;  
  38.             ans=max(ans,tmp);  
  39.         }  
  40.         printf("%d\n",ans+1);  
  41.         int tot=0;  
  42.         for(i=n-1;i>=0;i--){  
  43.             if(mark[i]==ans){  
  44.                 cnt[tot++]=p[i].idx;  
  45.                 ans--;  
  46.             }  
  47.         }  
  48.         sort(cnt,cnt+tot);  
  49.         for(i=0;i<tot;i++)  
  50.         {  
  51.             printf("%d",cnt[i]);  
  52.             if(i==tot-1) printf("\n");  
  53.             else printf(" ");  
  54.         }  
  55.     }  
  56.     return 0;  
  57. }  


H:

不知道题…  队友直接就给A了…  我就贴代码吧 - -b

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. #include<stdio.h>  
  2. #include<algorithm>  
  3. #include<iostream>  
  4. #include<string.h>  
  5. #include<math.h>  
  6. using namespace std;  
  7. typedef long long ll;  
  8. const int MAXN = 110;  
  9. #define MAX 2010  
  10. #define mod 10000  
  11. #define baselen 4  
  12. #define in(a) scanf("%d",&a)  
  13. #define out1(a) printf("%d",a)  
  14. #define out2(a) printf("%04d",a)  
  15. int a[MAXN][MAXN]; //增广矩阵  
  16. int x[MAXN]; //解集  
  17. bool free_x[MAXN]; //标记是否是不确定的变元  
  18. inline int abs(int a) {  
  19.     return a > 0 ? a : -a;  
  20. }  
  21. void Debug(int equ, int var) {  
  22.     int i, j;  
  23.     for (i = 0; i < equ; i++) {  
  24.         for (j = 0; j < var + 1; j++) {  
  25.             cout << a[i][j] << " ";  
  26.         }  
  27.         cout << endl;  
  28.     }  
  29.     cout << endl;  
  30. }  
  31. //m个方程,n个变量!!  
  32. int rank(int A[MAXN][MAXN], int m, int n) //求解01模2方程的秩!!  
  33.         {  
  34.     int i = 0, j = 0, k, r, u;  
  35.     while (i < m && j < n) //当前正在处理第i行,第j个变量!!  
  36.     {  
  37.         r = i;  
  38.         for (k = i; k < m; k++)  
  39.             if (A[k][j]) {  
  40.                 r = k;  
  41.                 break;  
  42.             }  
  43.         if (A[r][j]) {  
  44.             if (r != i)  
  45.                 for (k = 0; k <= n; k++)  
  46.                     swap(A[r][k], A[i][k]);  
  47.             for (u = i + 1; u < m; u++)  
  48.                 if (A[u][j])  
  49.                     for (k = i; k <= n; k++)  
  50.                         A[u][k] ^= A[i][k];  
  51.             i++;  
  52.         }  
  53.         j++;  
  54.     }  
  55.     return i; //系数矩阵的秩!  
  56. }  
  57. int p[1000], flag[1000], cnt = 0;  
  58. void get_prime() {  
  59.     int i, j;  
  60.     for (i = 2; i < 600; i++) {  
  61.         if (!flag[i])  
  62.             p[cnt++] = i;  
  63.         ;  
  64.         for (j = 0; j < cnt && p[j] * i < 600; j++) {  
  65.             flag[i * p[j]] = 1;  
  66.             if (i % p[j] == 0)  
  67.                 break;  
  68.         }  
  69.     }  
  70. }  
  71. int b[200];  
  72.    
  73. typedef int type;  
  74. /  
  75. struct bint {  
  76.     type dig[MAX], len;  
  77.     bint() {  
  78.         len = 0, dig[0] = 0;  
  79.     }  
  80. };  
  81.   
  82. //常用函数  
  83. //(1)  
  84. void add(bint a, bint b, bint& c) {  
  85.     type i, carry;  
  86.     for (i = carry = 0; i <= a.len || i <= b.len || carry; i++) {  
  87.         if (i <= a.len)  
  88.             carry += a.dig[i];  
  89.         if (i <= b.len)  
  90.             carry += b.dig[i];  
  91.         c.dig[i] = carry % mod;  
  92.         carry /= mod;  
  93.     }  
  94.     c.len = i - 1;  
  95. }  
  96. //(2)  
  97. void add(bint a, type b, bint& c) {  
  98.     type i;  
  99.     for (i = 0; i <= a.len || b; i++) {  
  100.         if (i <= a.len)  
  101.             b += a.dig[i];  
  102.         c.dig[i] = b % mod;  
  103.         b /= mod;  
  104.     }  
  105.     c.len = i - 1;  
  106. }  
  107. //(3)  
  108. void by(bint a, type b, bint& c) {  
  109.     type i, carry;  
  110.     for (i = carry = 0; i <= a.len || carry; i++) {  
  111.         if (i <= a.len)  
  112.             carry += b * a.dig[i];  
  113.         c.dig[i] = carry % mod;  
  114.         carry /= mod;  
  115.     }  
  116.     i--;  
  117.     while (i && !c.dig[i])  
  118.         i--;  
  119.     c.len = i;  
  120. }  
  121. //(4)  
  122. void by(bint a, bint b, bint& c) {  
  123.     type i, j, carry;  
  124.     for (i = a.len + b.len + 1; i >= 0; i--)  
  125.         c.dig[i] = 0;  
  126.     for (i = 0; i <= a.len; i++) {  
  127.         carry = 0;  
  128.         for (j = 0; j <= b.len || carry; j++) {  
  129.             carry += c.dig[i + j];  
  130.             if (j <= b.len)  
  131.                 carry += a.dig[i] * b.dig[j];  
  132.             c.dig[i + j] = carry % mod;  
  133.             carry /= mod;  
  134.         }  
  135.     }  
  136.     i = a.len + b.len + 1;  
  137.     while (i && c.dig[i] == 0)  
  138.         i--;  
  139.     c.len = i;  
  140. }  
  141. //(5)  
  142. void div(bint a, type b, bint& c, type& d) {  
  143.     type i;  
  144.     for (i = a.len, d = 0; i >= 0; i--) {  
  145.         d = d * mod + a.dig[i];  
  146.         c.dig[i] = d / b;  
  147.         d = d % b;  
  148.     }  
  149.     i = a.len;  
  150.     while (i && c.dig[i] == 0)  
  151.         i--;  
  152.     c.len = i;  
  153. }  
  154. //(6)  
  155. bool input(bint& a) {  
  156.     type i, j, w, k, p;  
  157.     char data[MAX * baselen + 1];  
  158.     if (scanf("%s", data) == EOF)  
  159.         return false;  
  160.     w = strlen(data) - 1, a.len = 0;  
  161.     for (p = 0; p <= w && data[p] == '0'; p++)  
  162.         ;  
  163.     while (1) {  
  164.         i = j = 0, k = 1;  
  165.         while (i < baselen && w >= p) {  
  166.             j = j + (data[w--] - '0') * k;  
  167.             k *= 10, i++;  
  168.         }  
  169.         a.dig[a.len++] = j;  
  170.         if (w < p)  
  171.             break;  
  172.     }  
  173.     a.len--;  
  174.     return true;  
  175. }  
  176. //(7)  
  177. void output(bint& a) {  
  178.     type i;  
  179.     i = a.len - 1;  
  180.     out1(a.dig[a.len]);  
  181.     while (i >= 0)  
  182.         out2(a.dig[i--]);  
  183.     printf("\n");  
  184. }  
  185.   
  186. //少用函数  
  187. //(8)  
  188. void move(bint& a) {  
  189.     type carry, k, t;  
  190.     k = a.len + 1, carry = 0;  
  191.     while (k--) {  
  192.         t = a.dig[k] & 1;  
  193.         a.dig[k] = (a.dig[k] >> 1);  
  194.         if (carry)  
  195.             a.dig[k] += (mod >> 1);  
  196.         carry = t;  
  197.     }  
  198.     if (a.len && a.dig[a.len] == 0)  
  199.         a.len--;  
  200. }  
  201. //(9)  
  202. void sub(bint a, bint b, bint& c) {  
  203.     type i, carry;  
  204.     for (i = carry = 0; i <= a.len; i++) {  
  205.         c.dig[i] = a.dig[i] - carry;  
  206.         if (i <= b.len)  
  207.             c.dig[i] -= b.dig[i];  
  208.         if (c.dig[i] < 0)  
  209.             carry = 1, c.dig[i] += mod;  
  210.         else  
  211.             carry = 0;  
  212.     }  
  213.     i--;  
  214.     while (i && c.dig[i] == 0)  
  215.         i--;  
  216.     c.len = i;  
  217. }  
  218. //(10)  
  219. void sub(bint a, type b, bint& c) {  
  220.     type i;  
  221.     for (i = 0; i <= a.len; i++) {  
  222.         c.dig[i] = a.dig[i] - b;  
  223.         if (c.dig[i] < 0)  
  224.             b = 1, c.dig[i] += mod;  
  225.         else  
  226.             b = 0;  
  227.     }  
  228.     i--;  
  229.     while (i && c.dig[i] == 0)  
  230.         i--;  
  231.     c.len = i;  
  232. }  
  233. //(11)  
  234. int cmp(bint a, bint b) {  
  235.     if (a.len < b.len)  
  236.         return -1;  
  237.     if (a.len > b.len)  
  238.         return 1;  
  239.     int i = a.len;  
  240.     while (i && a.dig[i] == b.dig[i])  
  241.         i--;  
  242.     return a.dig[i] - b.dig[i];  
  243. }  
  244. //(12)  
  245. void give(bint a, bint& b) {  
  246.     int i = 0;  
  247.     while (i <= a.len) {  
  248.         b.dig[i] = a.dig[i];  
  249.         i++;  
  250.     }  
  251.     b.len = a.len;  
  252. }  
  253. //(13)  
  254. void give(type a, bint& b) {  
  255.     b.dig[0] = a % mod;  
  256.     a /= mod;  
  257.     if (a > 0)  
  258.         b.dig[1] = a, b.len = 1;  
  259.     else  
  260.         b.len = 0;  
  261. }  
  262. //(14)  
  263. void shift(bint& a, type k) {  
  264.     int i;  
  265.     i = a.len + k;  
  266.     while (i >= k) {  
  267.         a.dig[i] = a.dig[i - k];  
  268.         i--;  
  269.     }  
  270.     while (i >= 0)  
  271.         a.dig[i--] = 0;  
  272.     a.len += k;  
  273. }  
  274. //(15)  
  275. void div(bint a, bint b, bint& c, bint& d) {  
  276.     type x, k;  
  277.     bint temp;  
  278.     give(a, d);  
  279.     c.len = c.dig[0] = 0;  
  280.     while (cmp(d, b) > 0) {  
  281.         k = d.len - b.len;  
  282.         if (d.dig[d.len] > b.dig[b.len])  
  283.             x = d.dig[d.len] / (b.dig[b.len] + 1);  
  284.         else if (k)  
  285.             k--, x = (d.dig[d.len] * mod + d.dig[d.len - 1])  
  286.                     / (b.dig[b.len] + 1);  
  287.         else  
  288.             break;  
  289.         by(b, x, temp);  
  290.         shift(temp, k);  
  291.         sub(d, temp, d);  
  292.         give(x, temp);  
  293.         shift(temp, k);  
  294.         add(c, temp, c);  
  295.     }  
  296.     if (cmp(d, b) >= 0)  
  297.         sub(d, b, d), add(c, (type) 1, c);  
  298. }  
  299. int main() {  
  300.     get_prime();  
  301.     //for(int i=0;i<=100;i++)printf("%d  %d\n",i+1,p[i]);  
  302.     int i, j, t, m;  
  303.     while (~scanf("%d%d", &t, &m)) {  
  304.         int xx;  
  305.         memset(a, 0, sizeof(a));  
  306.         for (i = 0; i < m; i++) {  
  307.             scanf("%d", &xx);  
  308.             for (j = 0; j < t; j++)  
  309.                 while (xx % p[j] == 0) {  
  310.                     xx /= p[j];  
  311.                     a[j][i] ^= 1;  
  312.                 }  
  313.         }  
  314.         //Debug(maxp+1,n);  
  315.         int r = rank(a, t, m);  
  316.         int y = m - r;  
  317.         if (y < 64) {  
  318.             ll ans = (1LL << y) - 1;  
  319.             printf("%lld\n", ans);  
  320.             continue;  
  321.         }  
  322.         bint tmp, Ans;  
  323.         give(1, Ans);  
  324.         while (y--) {  
  325.             tmp = Ans;  
  326.             by(tmp, 2, Ans);  
  327.         }  
  328.         tmp = Ans;  
  329.         sub(tmp, 1, Ans);  
  330.         output(Ans);  
  331.     }  
  332.     return 0;  
  333. }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值