2013ACM多校联合(2)
A:小Y做家教
简单的想法题。使用hash表或者是map存储所有数,然后从最小的数开始找从这个数开始的连续P倍数的个数X,那么需要删除的数的个数为X/2。
代码如下:
B:小Y的难题Ⅰ
组合数学题,通过经典的一一对应原则推导出答案为N^(N-2)。http://wenku.baidu.com/view/2e1ab2757fd5360cba1adbba.html
Cayley定理在组合数学中的应用。
代码如下:
#include <iostream> #include <cmath> #include <cstring> #include <cstdio> #include <string> #include <stdlib.h> using namespace std; typedef long long LL; const LL M=1e9+7; LL Pow( LL a, LL b) {LL ans=1;while( b ){if( b&1 ){ans*=a;ans%=M;}a*=a;a%=M;b>>=1; }return ans; } int main( ) {LL N;while( scanf( "%lld", &N )!=EOF ){printf( "%lld\n", Pow( N, N-2 ) );}return 0; }
C:小Y的逆袭
计算几何。该题一个简单的做法是先找出三个点的外心,然后用极坐标每次旋转72°生成剩下的点。
代码如下:
#include <cstring> #include <cstdio> #include <cstdlib> #include <algorithm> #include <iostream> #include <cmath> #include <vector> using namespace std;const double PI = acos(-1);struct point{double x,y;}; struct line{point a,b;}; vector<point>v;point p[3], cc;point intersection(line u,line v){point ret=u.a;double t=((u.a.x-v.a.x)*(v.a.y-v.b.y)-(u.a.y-v.a.y)*(v.a.x-v.b.x))/((u.a.x-u.b.x)*(v.a.y-v.b.y)-(u.a.y-u.b.y)*(v.a.x-v.b.x));ret.x+=(u.b.x-u.a.x)*t;ret.y+=(u.b.y-u.a.y)*t;return ret; }point circumcenter(point a,point b,point c){line u,v;u.a.x=(a.x+b.x)/2;u.a.y=(a.y+b.y)/2;u.b.x=u.a.x-a.y+b.y;u.b.y=u.a.y+a.x-b.x;v.a.x=(a.x+c.x)/2;v.a.y=(a.y+c.y)/2;v.b.x=v.a.x-a.y+c.y;v.b.y=v.a.y+a.x-c.x;return intersection(u,v); }double dist(point a, point b) {return sqrt(double( (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y) )); }bool cmp(point a, point b) {if (fabs(a.x - b.x) > 1e-6) {return a.x < b.x;} else {return a.y < b.y;} }int main() {double R;point info;while (scanf("%lf %lf", &p[0].x, &p[0].y) != EOF) {v.clear();for (int i = 1; i < 3; ++i) {scanf("%lf %lf", &p[i].x, &p[i].y);}cc = circumcenter(p[0], p[1], p[2]);R = dist(p[0], cc);double phi = atan2(p[0].y-cc.y, p[0].x-cc.x); // 求出第一个点的角度for (int i = 0; i < 5; ++i) {info.x = R * cos(phi) + cc.x, info.y = R * sin(phi) + cc.y;v.push_back(info);phi += 72.0*PI/180.0;}sort(v.begin(), v.end(), cmp);for (int i = 0; i < 5; ++i) {int flag = 0;for (int j = 0; j < 3; ++j) {if (fabs(v[i].x - p[j].x) < 1e-6 && fabs(v[i].y - p[j].y) < 1e-6) {flag = 1;break;}}if (!flag) {printf("%.2f %.2f\n", v[i].x, v[i].y);}}}return 0; }
D:Palindrome
动态规划。题意是求将一个串改造成回文串的最少花费。给出所有组成串的字母添加和删除的花费。设dp[i][j]表示[i,j]子串被改造成回文串的最少开销是多少。那么有动态规划方程:
dp[i][j] = min(dp[i+1][j] + cost[i], dp[i][j-1] + cost[j]); 其中cost[i] = min(add[i], del[i])存储删除和添加节点的较小的花费。如果str[i] == str[j]的话就多出一种选择dp[i-1][j-1]。
代码如下:
#include <cstdlib> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm>using namespace std; int N, M, dp[2005][2005]; int cost[30]; char str[2005];int DP() {for (int i = 1; i < M; ++i) {for (int j = 1; j+i <= M; ++j) {int a = j, b = j + i, ll = str[a]-'a', rr = str[b]-'a';dp[a][b] = min(dp[a+1][b] + cost[ll], dp[a][b-1] + cost[rr]);if (ll == rr)dp[a][b] = min(dp[a][b], dp[a+1][b-1]);}}return dp[1][M]; }int main() {char s[5];int a, b;while (scanf("%d %d", &N, &M) == 2) {scanf("%s", str+1);for (int i = 1; i <= N; ++i) {scanf("%s %d %d", s, &a, &b);cost[s[0]-'a'] = min(a, b);}printf("%d\n", DP());}return 0; }
E:小Y的难题Ⅱ
分解素因子,转换成M个球放到N个盒子模型,得出组合公式C(N+M-1, N-1),因为ai>1,既盒子不允许为空,所以求出总方案数后,减去盒子为空的情形。对于盒子为空的求解,通过假设至少一个盒子(C(N+M-1-1,M-1-1)),两个,直到N-1个,由容斥来解决重复问题。注意单个素因子,其次数可能会很大,所以C预处理要比较大,不然会RE。
代码如下:
#include<cstdio> #include<cstring> #include<cstdlib> #include<assert.h> #include<algorithm> #include<map> #include<cmath> using namespace std; typedef long long LL;const int mod = 1e9+7;int b[21], a[1010], n, tot; LL C[1100][1100];map<int,int>mp;void init(){for(int i = 0; i <= 1000; i++)C[i][0] = 1, C[i][i] = 1;for(int i = 2; i <= 1000; i++)for(int j = 1; j < i; j++)C[i][j] = (C[i-1][j-1]+C[i-1][j])%mod; }void deal(){mp.clear();for(int i = 0; i < n; i++){int tmp_max = (int)sqrt(1.*b[i]);int t = b[i];for(int j = 2; j <= tmp_max; j++){if( t%j == 0 ){if( mp.count(j) == 0 ) mp[j] = 0;int cnt = 0; while( t%j == 0 ) (t/=j), cnt++;mp[j] += cnt;} }if( t > 1 ){if( mp.count(t) == 0 ) mp[t] = 1;else mp[t]++;} }int idx = 0;memset( a, 0, sizeof(a));for( map<int,int>::iterator it = mp.begin(); it != mp.end(); it++ )a[idx++] = it->second;tot = mp.size(); } void solve(){LL ans = 0;for(int i = 0; i < n; i++){LL tmp = 1;for(int j = 0; j < tot; j++){ assert( (((n-1-i+a[j])>=0)&&(n-1-i+a[j])<=1000) ); tmp = tmp*C[ n-1-i+a[j] ][ n-1-i ]%mod; }tmp = tmp*C[n][i]%mod;if( i&1 ) tmp = -tmp;ans = (ans+tmp+mod)%mod;}printf("%lld\n", ans); } int main(){init();int T;scanf("%d", &T);while( T-- ){scanf("%d", &n);for(int i = 0; i < n; i++)scanf("%d", &b[i] );deal();solve();}return 0; }
F:War Ⅰ
并查集+最短路。通过并查集处理结盟的点,然后从集合中选择一个到目标点最短的距离输出。
代码如下:
#include<iostream> #include<stdio.h> #include<string.h>using namespace std;const int inf = 0x7f7f7f7f; const int MAXV = 1002;int UFS[MAXV];int Find(int x) {return UFS[x]=(UFS[x]!=x?Find(UFS[x]):x); } void Union(int x,int y) {UFS[Find(x)]=Find(y); }char o; int n,m,k,u,v,w,x,y,a[MAXV][MAXV];int main() {while(scanf("%d %d %d",&n,&m,&k)!=EOF){memset(a,inf,sizeof(a));for(int i=0;n>i;i++){UFS[i]=i;}for(int i=0;m>i;i++){scanf("%d %d %d",&u,&v,&w);a[u][v]=min(a[u][v],w);}for(int z=0;n>z;z++){for(int i=0;n>i;i++){if(a[i][z]!=inf){for(int j=0;n>j;j++){if(a[z][j]!=inf){a[i][j]=min(a[i][j],a[i][z]+a[z][j]);}}}}}for(int i=0;k>i;i++){getchar();scanf("%c %d %d",&o,&x,&y);if(o=='I') Union(x,y);else{int ans=inf;for(int i=0;n>i;i++){if(Find(x)==Find(i)){ans=min(ans,a[i][y]);}}printf("%d\n",ans!=inf?ans:-1);}}}return 0; }
G:War Ⅱ
二分枚举构图+二分匹配。该题想说明的就是A中的一个城市只能够对应B中的一个城市。先通过floyd求出任意城市之间的最短路,然后二分枚举构好A->B城市的二分图,然后使用匈牙利算法计算是否能够达到完全匹配。
代码如下:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <ctime> #include <cassert> using namespace std;const int MAX = 105; const int INF = 0x3f3f3f3f; int n, N, M, reca[MAX], recb[MAX]; int mp[MAX][MAX]; int marry[MAX]; char G[MAX][MAX]; char vis[MAX];void floyd() {for (int k = 0; k < n; ++k) {for (int i = 0; i < n; ++i) {if (mp[i][k] == INF || i == k) continue;for (int j = 0; j < n; ++j) {if (mp[k][j] == INF || j == k) continue;if (mp[i][j] > mp[i][k] + mp[k][j]) {mp[i][j] = mp[i][k] + mp[k][j];}}} } }bool path(int u) {for (int i = 0; i < M; ++i) {if (!G[u][i] || vis[i])continue;vis[i] = 1;if (marry[i] == -1 || path(marry[i])) {marry[i] = u;return true;}}return false; }void build(int lim) {memset(G, 0, sizeof (G));for (int i = 0; i < N; ++i) {for (int j = 0; j < M; ++j) {if (mp[reca[i]][recb[j]] <= lim) {G[i][j] = 1;}}} }bool Ac() {int cnt = 0;memset(marry, 0xff, sizeof (marry));for (int i = 0; i < N; ++i) {memset(vis, 0, sizeof (vis));if (path(i)) {++cnt;}}return cnt == M; }int bsearch(int l, int r) {int mid, ret;while (l <= r) {mid = (l + r) >> 1;build(mid);if (Ac()) {ret = mid;r = mid - 1; } else {l = mid + 1;}}return ret; }int main() {while (scanf("%d", &n) == 1) {for (int i = 0; i < n; ++i) {for (int j = 0; j < n; ++j) {scanf("%d", &mp[i][j]);}}scanf("%d", &N);for (int i = 0; i < N; ++i) {scanf("%d", &reca[i]);--reca[i];}scanf("%d", &M);for (int i = 0; i < M; ++i) {scanf("%d", &recb[i]);--recb[i];}floyd();printf("%d\n", bsearch(0, 10000));}return 0; }
H:War Ⅲ
法一:通过题目给定的关系不难知道a[i] = 3*a[i-1] + a[i-2] - 3*a[i-3]。假设要求第D天的口令,那么计算出a[D-1], a[D-2], a[D-3]就能够计算出a[D],求出四个系数后,代入X便可求解答案了。这题D给的数据比较大,直接计算肯定会TLE,那么使用矩阵并加上快速降幂来计算就简单多了,将给定的b,c,d作为3*1的矩阵B{a[0], a[-1], a[-2]}^-1,矩阵A=
3 1 -3
1 0 0
0 1 0
作为递推矩阵,那么在B矩阵左边乘上D-1个A最后的结果就是{a[D-1], a[D-2], a[D-3]}^-1,D-1个A相乘就可以使用矩阵快速幂了。
代码如下:
#include <iostream> #include <cstdlib> #include <cstdio> #include <cstring> #include <algorithm> #include <cassert> using namespace std;typedef long long int64; const int MOD = int(1e9)+7; int a, b, c, d, D, X;int64 R[3][3] = {{3, 1, -3},{1, 0, 0},{0, 1, 0} };struct Matrix {int64 mat[3][3];Matrix() {memset(mat, 0, sizeof (mat));}void unit() {memset(mat, 0, sizeof (mat));for (int i = 0; i < 3; ++i) {mat[i][i] = 1;}}void init() {memcpy(mat, R, sizeof (mat));}void show() const;friend Matrix operator * (const Matrix & a, const Matrix & b);friend Matrix pow(Matrix a, int b); };void Matrix::show() const {for (int i = 0; i < 3; ++i) {for (int j = 0; j < 3; ++j) {printf("%d ", mat[i][j]); }puts("");} }Matrix operator * (const Matrix & a, const Matrix & b) {Matrix ret;for (int i = 0; i < 3; ++i) {for (int j = 0; j < 3; ++j) {for (int k = 0; k < 3; ++k) {ret.mat[i][j] += (a.mat[i][k] * b.mat[k][j]) % MOD;ret.mat[i][j] %= MOD;}}}return ret; }Matrix pow(Matrix a, int b) {Matrix ret;ret.unit();while (b) {if (b & 1) {ret = ret * a;}a = a * a;b >>= 1;}return ret; }int64 cal(int64 na, int64 nb, int64 nc, int64 nd) {int64 ini[4] = {1};for (int i = 1; i < 4; ++i) {ini[i] = (ini[i-1] * X) % MOD;}return ((na*ini[3])%MOD+(nb*ini[2])%MOD+(nc*ini[1])%MOD+(nd*ini[0])%MOD)%MOD; }void solve() {Matrix mm; mm.init();mm = pow(mm, D-1);int64 na, nb, nc, nd;nb = ((mm.mat[0][0]*b)%MOD + (mm.mat[0][1]*c)%MOD + (mm.mat[0][2]*d)%MOD)%MOD;nc = ((mm.mat[1][0]*b)%MOD + (mm.mat[1][1]*c)%MOD + (mm.mat[1][2]*d)%MOD)%MOD;nd = ((mm.mat[2][0]*b)%MOD + (mm.mat[2][1]*c)%MOD + (mm.mat[2][2]*d)%MOD)%MOD;na = (3*nb)%MOD+nc-(3*nd)%MOD;printf("%d\n", int((cal(na, nb, nc, nd)+MOD)%MOD)); }int main() {while (scanf("%d %d %d %d", &a, &b, &c, &d) != EOF) {assert(a >= 0 && a <= 100);scanf("%d %d", &D, &X);solve();}return 0; }
法二:根据表达式a[i] = 3*a[i-1] + a[i-2] - 3*a[i-3],由于该表达式为常系数3阶齐次递推关系,因此设a[n] = r^n,代入方程求出特征根为-1,1,3,因此a[n]=A*(-1)^n+B*(1)^n+C*(3)^n,令a[0]=d,a[1]=c,a[2]=b求出A,B,C之后再根据通项公式求出D天后的系数。b,c,d是8的倍数保证了解三元一次方程组时不会出现分数。
代码如下:
#include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> using namespace std;typedef long long int64; const int64 MOD = (int64)1e9 + 7; int64 a, b, c, d, D, X;int64 _pow(int64 a, int64 b) {int64 ret = 1;while (b) {if (b & 1) {ret *= a;ret %= MOD;}b >>= 1;a *= a;a %= MOD;}return ret; }int64 cal(int64 na, int64 nb, int64 nc, int64 nd) {int64 ini[4] = {1};for (int i = 1; i < 4; ++i) {ini[i] = (ini[i-1] * X) % MOD;}return ((na*ini[3])%MOD+(nb*ini[2])%MOD+(nc*ini[1])%MOD+(nd*ini[0])%MOD)%MOD; }int main() {while (scanf("%lld %lld %lld %lld", &a, &b, &c, &d) != EOF) {scanf("%lld %lld", &D, &X);int64 A = (3*d-4*c+b)/8;int64 B = (3*d+2*c-b)/4;int64 C = (b-d)/8;a = (A * ((D+2) & 1 ? -1 : 1) + B + C * _pow(3, D+2)) % MOD;b = (A * ((D+1) & 1 ? -1 : 1) + B + C * _pow(3, D+1)) % MOD;c = (A * ((D) & 1 ? -1 : 1) + B + C * _pow(3, D)) % MOD;d = (A * ((D-1) & 1 ? -1 : 1) + B + C * _pow(3, D-1)) % MOD;printf("%lld\n", (cal(a, b, c, d)+MOD)%MOD);}return 0; }
转载于:https://www.cnblogs.com/Lyush/archive/2013/03/30/2990715.html
2013ACM多校联合(2)相关推荐
- 2022 七校联合NewStarCTF 公开赛赛道 WEEK3|MISC
1.Whats HTTP 2.qsdz's girlfriend 3 3.WebShell! hint提示蚁剑,根据流量包大小排序,逐个打开看 4.Yesec no drumsticks 3 压缩包第 ...
- 华中科技大学辅修计算机双学位,关于做好“七校联合办学”辅修专业、双学位的通知...
华中科技大学教务处发表的通知内容如下: 各院(系): 2014-2015学年武汉大学.华中科技大学.华中师范大学.武汉理工大学.中国地质大学.中南财经政法大学.华中农业大学等七校联合办学报名工作即将开 ...
- 2018六校联合校赛-1st-买手机
题目描述: 阿Jun是个小屏手机爱好者,他拒绝一切带有plus和note字眼的手机,而他一直使用的是一部美国苹果公司出品的iPhoneSE. 可惜的是,有一次阿Jun在洗手间洗手,不小心手一抖,手机掉 ...
- HDU 2019 Multi-University Training Contest 1 杭电2019多校联合训练赛 第一场 1001 Blank (6578)
HDU 2019 Multi-University Training Contest 1 杭电2019暑期多校集训第一场 1001 Blank (6578) Problem Description T ...
- 2018ACM暑期多校联合训练参(bao)赛(zha)记
(这毁了我一个暑假的东西) 时间 2018-7-23至2018-8-22,一星期2场,共10场,每场5个小时. 题目链接(楼教主:"是男人就过八(116)题") 评分规则 单场得分 ...
- 关于南京四校联合程序设计大赛
近期南京的东南大学.南京大学.南京航空航天大学和南京理工大学的微软俱乐部联合举行了一个基于微软技术的程序设计大赛,2008年12月14号我应邀去东南大学的九龙湖校区参加了一个学生软件开发项目比赛的复赛 ...
- HDU 5734 Acperience (公式推导) 2016杭电多校联合第二场
题目:传送门. #include <iostream> #include <algorithm> #include <cstdio> #include <cs ...
- 2017ACM暑期多校联合训练 - Team 7 1009 HDU 6128 Inverse of sum (数学计算)
题目链接 Problem Description There are n nonnegative integers a1-n which are less than p. HazelFan wants ...
- 2013 多校联合4 1011 Fliping game (hdu 4642)
题意:在一个矩阵中放着可上可下的银币,你可以翻一个矩形里面的银币使它们变成相反的方向,但此矩型必须是右下角是矩阵的最右下角,左上角这个点必须是朝上的.最 后结束的标志是所有的银币都已经都是朝上的,此时 ...
最新文章
- python03-异常处理
- RocketMQ简介
- Windows保护模式学习笔记(十)—— TLB
- 利用cookie显示上次浏览的时间
- web服务器的文档根目录,web服务器根目录中
- approach for doing things
- StringBuffer 案例
- [Linux] 权限与指令间的关系
- Docker的常用操作
- Android 功耗(8)---如何找到阻止进入deep idle / SODI的元凶
- 三星Galaxy Fold全球翻车后 推迟发售时间进一步改进
- tensorflow 读取cifar_对tensorflow中cifar-10文档的Read操作详解
- LINQ简记(3):子句
- 微软官方提供的免费正版 Windows 8.1/Win10/7/XP/Vista 操作系统虚拟机镜像下载
- 360浏览器cookie的导出
- android 辅助音量放大,为什么总是感觉手机音量太小?教你开启这个功能,声音瞬间放大一倍...
- 2021年十大潜力行业
- 13.5 Prepared Statements
- 阿里云数据库RDS如何用Navicat连接?
- MySQL-7 DDL约束 标识列 TCL事务控制语言 视图view