SDUACM暑期集训周赛(五)
来源:互联网 发布:安装包 制作软件 编辑:程序博客网 时间:2024/06/14 12:09
BZOJ 2186 沙拉公主的困惑
[Problem]
询问n!中与m!互质的个数(n > m)
[Solution]
ans = n! / m ! * phi(m!)
显然[1, m!] 此区间中有phi(m!)个与m!互质的数
[m! + 1, m! + m!] 同样有phi(m!)个 gcd(m! + i, m !) = gcd(i, m!)
[2 * m! + 1, 3 * m!] phi(m!) 个
…….
[Code]
#include <cstdio> #define ll long long #define maxn 10000000 #define maxk 1000000 using namespace std; ll p[maxk], R, inv[maxn+100], N, M, tot, fac[maxn+100], ans[maxn+100], T; bool no[maxn+100]; void getinv() { int i, m=(R<maxn?R:maxn); inv[1]=1; for(i=2;i<m;i++)inv[i]=(ll)(R-R/i)*inv[R%i]%R; } void shai() { int i, j; for(i=2;i<=maxn+1;i++) { if(!no[i])p[++tot]=i; for(j=1;i*p[j]<=maxn;j++) { no[i*p[j]]=true; if(i%p[j]==0)break; } } } void getfac() { int i; fac[1]=1; for(i=2;i<=maxn;i++)fac[i]=fac[i-1]*i%R; } void getans() { int i, j; ll t; ans[1]=1; for(i=1;i<=tot;i++) { t=(ll)ans[p[i]-1]*(p[i]-1)%R*inv[p[i]%R]%R; for(j=p[i];j<p[i+1];j++)ans[j]=t; } } int main() { int i; scanf("%d%d",&T,&R); shai(); getinv(); getfac(); getans(); while(T--) { scanf("%d%d",&N,&M); printf("%lld\n",fac[N]*ans[M]%R); } return 0; }
BZOJ 2186 POJ 2992 Divisors
[Solution]
把每个数字分解质因数,然后把结果存到数组中,前缀和累加一下,对于计算cnm时用幂进
行运算
[Code]
#include<cstdio>#include<iostream>#include<cstring>using namespace std;#define N 1000int p[500], top = 0, ans[500];int num[N][N], n, m, sum[N][N];bool isp[N];long long f[N][N];void cal(int n, int m){ for(int i = 1; i <= top; i++) ans[i] = 0; if (n - m < m) m = n - m; if (f[n][m]) return; for(int j = 1; j <= top; j++) { ans[j] = sum[n][j] - sum[m][j] - sum[n - m][j]; }}void init(){ for(int i = 2; i <= 431; i++) { if (isp[i]) continue; p[++top] = i; for(int j = i; j <= 431; j += i) isp[j] = true; } for(int i = 2; i <= 431; i++) { int x = i; for(int j = 1; j <= top; j++){ while (x % p[j] == 0) { num[i][j]++; x /= p[j]; } } } for(int i = 2; i <= 431; i++) { for(int j = 1; j <= top; j++) { sum[i][j] += sum[i - 1][j] + num[i][j]; } }}int main(){ // freopen("b.in", "r", stdin); init(); while(~scanf("%d%d", &n, &m)) { cal(n, m); if (f[n][m]) { cout << f[n][m] << endl; continue; } long long cur = 1LL; for(int i = 1; i <= top; i++) cur *= (ans[i] + 1); f[n][m] = cur; f[n][n - m] = cur; cout << cur << endl; } return 0;}
POJ 1696 Space Ant
[Solution]
每次向左偏转的角度尽可能地小,判断点是不是在左边通过叉积计算
[Code]
#include <cstdio>#include <cmath>#include <algorithm>using namespace std;#define N 2000const double eps = 1e-9;int n, top;bool f[N];struct Point { double x, y; int num;} a[N];int ans[N];bool cmp(Point a, Point b){ if (a.y == b.y) return a.x < b.x; return a.y < b.y;}int Cross(Point p0, Point p1, Point p2) { double tot = (p1.x-p0.x)*(p2.y-p0.y)-(p1.y-p0.y)*(p2.x-p0.x); if (fabs(tot) < eps) return 0; return tot < 0 ? -1 : 1;}double dis(Point u, Point v){ return sqrt((u.x - v.x) * (u.x - v.x) + (u.y - v.y) * (u.y - v.y));}bool lcmp(Point u, Point v1, Point v2){ int d = Cross(u, v2, v1); if (!d) return dis(u, v2) < dis(u, v1); return d > 0;}int main(){ //freopen("b.in", "r", stdin); int T; scanf("%d", &T); while(T--) { scanf("%d", &n); for(int i = 1; i <= n; i++) scanf("%d%lf%lf", &a[i].num, &a[i].x, &a[i].y); sort(a + 1, a + n + 1, cmp); for(int i = 1; i <= n; i++) f[i] = false; ans[1] = a[1].num; f[1] = true; Point lastu; lastu.x = 0; lastu.y = a[1].y; Point u = a[1]; int top = 1; for(int i = 2; i <= n; i++) { int minj = -1; for(int j = 2; j <= n; j++) { if (!f[j] && (Cross(lastu, u, a[j]) >= 0)) { if (minj < 0 || lcmp(u, a[minj], a[j])) minj = j; } } if (minj < 0) break; ans[++top] = a[minj].num; f[minj] = true; lastu = u; u = a[minj]; } printf("%d", top); for(int i = 1; i <= top; i++) printf(" %d", ans[i]); printf("\n"); } return 0;}
POJ 1319 Pipe Fitters
[Solution]
对于第一种放置方式,直接是(int)a * (int)b
对于第二种放置方式,最后一行可以防止(int)b, 倒数第二层取决于b的小数部分
需要高度与实际高度的比例可以推出
注意第二种放置方式始终有一层的高度是无法优化的
注意第二种放置方式把a当行一次,把b当行一次
[Code]
#include<cstdio>#include<iostream>#include<cstring>#include<cmath>using namespace std;int cal(double a, double b){ int d1 = (int)b, d2 = (int) (b + 0.5); d2--; int k = (int)((a - 1) * 2 / sqrt(3.0)); // important if (a >= 1) k++; int ans2 = (k / 2) * (d1 + d2); if (k % 2) ans2 += d1; return ans2;}int main(){ // freopen("b.in", "r", stdin); double a, b; while (~scanf("%lf%lf", &a, &b)) { int ans1 = (int)a * (int)b; int ans2 = max(cal(a, b), cal(b, a)); if (ans1 >= ans2) printf("%d grid\n", ans1); else printf("%d skew\n", ans2); } return 0;}
HDU 3746 Cyclic Nacklace
[Solution]
kmp判断
首先考虑虽然我们可以添加到左边,也可以添加到右边,但实际上等效于添加到一边,因为最终会连成一个环。
因此我们只思考在字符串的右面加上一些字符,考虑最后一位的next值,len-next[len]为循环节长度d, next[len] % d 便是最后多的那一部分
[Code]
#include<cstdio>#include<iostream>#include<cstring>using namespace std;#define N 200500char c[N];int nxt[N];void get_next(char* s, int* nxt){ int n = strlen(s); int j = 0; nxt[0] = nxt[1] = 0; for(int i = 1; i < n; i++){ while (j > 0 && s[i] != s[j]) j = nxt[j]; if (s[i] == s[j]) j++; nxt[i + 1] = j; }}int main(){ // freopen("b.in", "r", stdin); int T; scanf("%d", &T); while (T--) { scanf("%s", c); get_next(c, nxt); int len = strlen(c); int ans = len - nxt[len]; int t = nxt[len] % ans; if (!t && nxt[len]) t = ans; printf("%d\n", ans - t); } return 0;}
BZOJ 2186 沙拉公主的困惑
[Solution]
只想说尽可能不会再把数字转成字符串处理了
[Code]
#include<cstdio>#include<iostream>#include<cstring>using namespace std;#define N 3010#define M 2#define ll long longint cnt = 0;int id[N * 34], ch[N * 34][2], tim[N * 34];int pow[33];int n, m;int a[N];void init(){ cnt = 0; for(int i = 0; i < M; i++) ch[0][i] = 0; id[0] = 0; tim[0] = -1;}void insert(int x, int k){ int u = 0; for(int i = 30; i >= 0; i--) { int v = (x & (1 << i)) > 0 ? 1 : 0; if (!ch[u][v]) { ch[u][v] = ++cnt; for(int j = 0; j < M; j++) ch[cnt][j] = 0; id[cnt] = 0; tim[cnt] = 0; } u = ch[u][v]; tim[u]++; } id[u] = k;}void update(int x, int t){ int u = 0; for(int i = 30; i >= 0; i--) { int v = (x & (1 << i)) > 0 ? 1 : 0; u = ch[u][v]; tim[u] += t; }}int cal(int x){ int u = 0; for(int i = 30; i >= 0; i--) { int v = (x & (1 << i)) > 0 ? 1 : 0; if (ch[u][1 - v] && tim[ch[u][1 - v]]) u = ch[u][1 - v]; else u = ch[u][v]; } return id[u];}int main(){ // freopen("b.in", "r", stdin); int T; scanf("%d", &T); while(T--) { init(); scanf("%d", &n); for(int i = 1; i <= n; i++) { scanf("%d", a + i); insert(a[i], i); } int ans = 0; for(int i = 1; i <= n; i++) { update(a[i], -1); for(int j = i + 1; j <= n; j++) { update(a[j], -1); int k = cal(a[i] + a[j]); ans = max(ans, ((a[i] + a[j]) ^ a[k])); //printf("%d %d %d\n", i, j, k); update(a[j], 1); } update(a[i], 1); } printf("%d\n", ans); } return 0;}
阅读全文
0 0
- SDUACM暑期集训周赛(五)
- SDUACM暑期集训周赛(二)
- HDOJ2009暑期集训内部赛(5)
- 暑期集训(首篇博文)
- 暑期集训第二周---搜索
- 暑期集训-dp(1)
- 暑期集训
- 记2013暑期集训总结赛
- 大一暑期集训训练赛一
- HPU2017-2016级暑期集训练习赛
- HPU2017-2016级暑期集训练习赛
- 2016-2017 HPU暑期集训练习赛
- HDOJ2009暑期集训公开赛(6)
- 暑期集训搜索专题(一)
- 暑期集训搜索专题(一)
- 暑期集训day1训练(图论1)
- 暑期集训day3训练(数据结构)
- HPU16级暑期集训练习(一)
- Spark基础-Scala高阶函数
- Chrome扩展程序——TabCopy:一键复制网页标题和网址
- STM32F103+RTT从零开始(一)——点亮LED
- GPS-NEO-6M的调试过程
- eclipse配置并使用Maven
- SDUACM暑期集训周赛(五)
- 自我总结(集训女队员导致的后续事件)
- PHP的翻页功能
- Java Arrays类的 用法解析
- sql面试题
- [LG1503] 鬼子进村
- UVA Live 7693 (Codeforces Gym 101201B) Buggy Robot DP+bfs
- Maven简介和环境配置
- 【POJ】1862