山东省第四届ACM省赛
解题报告:http://www.tuicool.com/articles/FnEZJb
A.Rescue The Princess(几何,向量)
B.The number of steps(记忆化搜索,概率dp)
C.Boring Counting(划分树)
D.A-Number and B-Number(数位dp,二分答案)
E.Alice and Bob
F.Mountain Subsequences(dp)
G.Rubik’s cube(哈希+bfs)
H.A^X mod P(转化求幂,打表)
I.Thrall’s Dream(bfs/dfs)
J.Contest Print Server(模拟)
A.Rescue The Princess
d.逆时针给出两个点A、B,求出逆时针构成正三角形的第三个点C。(即A、B、C为逆时针)
s.
法1.
法2.向量旋转公式,证明见:http://www.cnblogs.com/bofengyu/p/5394969.html
c.法1
#include<iostream>
#include<stdio.h>
#include<math.h>
using namespace std; const double PI=*atan(); int main(){ int T;
double x1,x2,x3;
double y1,y2,y3;
double theta;
double len; scanf("%d",&T); while(T--){
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); theta=atan2(y2-y1,x2-x1);//不能用atan(),原因是atan不分辨一、三象限,也不分辨二、四象限
len=sqrt((y2-y1)*(y2-y1)+(x2-x1)*(x2-x1)); x3=x1+len*cos(theta+PI/);
y3=y1+len*sin(theta+PI/); printf("(%.2f,%.2f)\n",x3,y3); } return ;
}
c2.法2.向量旋转公式
#include<iostream>
#include<stdio.h>
#include<math.h>
using namespace std; const double PI=acos(-); int main(){ int T;
double x1,x2,x3;
double y1,y2,y3;
double sin60=sin(PI/);
double cos60=cos(PI/); scanf("%d",&T); while(T--){
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2); x3=(x2-x1)*cos60-(y2-y1)*sin60+x1;
y3=(x2-x1)*sin60+(y2-y1)*cos60+y1; printf("(%.2f,%.2f)\n",x3,y3); } return ;
}
B.The number of steps
C.Boring Counting
s.应该用划分树
c.线段树写的超时了。
/*
线段树
单点更新
*/
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std; #define L(root) ((root)<<1)
#define R(root) (((root)<<1)|1) const int MAXN=;//
int numbers[MAXN];//初始值
int A,B; struct node{
int left,right;//
//int sum;
int ma,mi;
int mid(){
return left+((right-left)>>);
}
}tree[MAXN*];//4倍空间 void pushUp(int root){
//tree[root].sum=tree[L(root)].sum+tree[R(root)].sum;
tree[root].ma=tree[L(root)].ma>tree[R(root)].ma?tree[L(root)].ma:tree[R(root)].ma;
tree[root].mi=tree[L(root)].mi<tree[R(root)].mi?tree[L(root)].mi:tree[R(root)].mi;
} void build(int root,int left,int right){
tree[root].left=left;
tree[root].right=right;
if(left==right){
//tree[root].sum=numbers[left];
tree[root].ma=tree[root].mi=numbers[left];
return;
}
int mid=tree[root].mid();
build(L(root),left,mid);
build(R(root),mid+,right);
pushUp(root);
} int query(int root,int left,int right){
if(tree[root].left==left&&tree[root].right==right){
//return tree[root].sum;
if(A<=tree[root].mi&&tree[root].ma<=B){
return right-left+;
}
if(tree[root].left==tree[root].right){
return ;
}
int mid=tree[root].mid();
return query(L(root),left,mid)+query(R(root),mid+,right);
}
int mid=tree[root].mid();
if(right<=mid){
return query(L(root),left,right);
}
else if(left>mid){
return query(R(root),left,right);
}
else{
return query(L(root),left,mid)+query(R(root),mid+,right);
}
}
/*
void update(int root,int pos,int add){
if(tree[root].left==tree[root].right){
tree[root].sum+=add;
return;
}
int mid=tree[root].mid();
if(pos<=mid){
update(L(root),pos,add);
}
else{
update(R(root),pos,add);
}
pushUp(root);
}
*/ int main(){
/*
memset(numbers,0,sizeof(numbers)); int i;
for(i=1;i<MAXN;++i){
numbers[i]=i;
} build(1,1,10); cout<<query(1,2,3)<<endl; update(1,2,100);
cout<<query(1,2,3)<<endl;
*/ int T;
int N,M;
int L,R;//,A,B;
int i;
int Case=; scanf("%d",&T); while(T--){
scanf("%d%d",&N,&M); for(i=;i<=N;++i){
scanf("%d",&numbers[i]);
}
build(,,N); printf("Case #%d:\n",++Case);
for(i=;i<M;++i){
scanf("%d%d%d%d",&L,&R,&A,&B);
printf("%d\n",query(,L,R));
}
} return ;
}
D.A-Number and B-Number
E.Alice and Bob
F.Mountain Subsequences
G.Rubik’s cube
H.A^X mod P
s.在求A^X幂时,直接快速幂求的话,是O(10^6*log(n)*40)=O(10^9) 肯定会超时。
我们将X转化成x=i*k+j。这样先在数组可以表示的范围内找到一个k,然后保存(A^0)~(A^k)的值,然后再将求出(A^k)^i 保存在数组里,
这样每次求A^x,便可以通过这两个数组在O(1)的时间复杂度内求出来,这样时间复杂度就变成了O(10^6*40) = O(4*10^7)了
#include<iostream>
#include<stdio.h>
using namespace std; #define ll long long #define N 31622
#define M 33333 ll powA[N+];
ll powB[M+]; ll n,A,K,a,b,m,P;
int cas; void init(){
powA[]=;
for(int i=;i<=N;++i){
powA[i]=powA[i-]*A%P;
}
ll tmp=powA[N];
powB[]=;
for (int i=;i<=M;++i){
powB[i]=powB[i-]*tmp%P;
}
} void solve(){
ll fx=K;
ll ans=;
for(int i=;i<=n;++i){
ans=(ans+powB[fx/N]*powA[fx%N]%P)%P;
fx=(a*fx+b)%m;
}
printf("Case #%d: %lld\n",++cas,ans);
} int main(){
int T;
scanf("%d",&T); cas=;
while (T--){ scanf("%lld%lld%lld%lld%lld%lld%lld",&n,&A,&K,&a,&b,&m,&P);
init();
solve(); } return ;
}
I.Thrall’s Dream
d.这个题意我是着实没大看懂啊。。。英语不好。。
N个点,M条有向边,问这个图中任意两点是否可以到达。
s.直接枚举所有点,bfs或者dfs判断是否可达即可。
c.bfs
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<queue>
using namespace std; #define MAXN 2010
#define MAXM 10010 struct Edge{
int to,next;
}edge[MAXM];
int head[MAXN],tot; void addedge(int u,int v){
edge[tot].to=v;
edge[tot].next=head[u];
head[u]=tot++;
} void init(){
tot=;
memset(head,-,sizeof(head));
} bool d[MAXN][MAXN];//d[i][j]为true表示i可达j
bool vis[MAXN]; void bfs(int t){
memset(vis,false,sizeof(vis)); queue<int>myQueue;
int u,v;
int i; myQueue.push(t);
vis[t]=true; while(!myQueue.empty()){
u=myQueue.front();
myQueue.pop(); for(i=head[u];i!=-;i=edge[i].next){
v=edge[i].to;
if(!vis[v]){
d[t][v]=true;
vis[v]=true;
myQueue.push(v);
}
} }
} int main(){ int T;
int N,M;
int u,v;
int i,j;
bool flag;//
int Case=; scanf("%d",&T); while(T--){
scanf("%d%d",&N,&M); init();
for(i=;i<M;++i){
scanf("%d%d",&u,&v);
addedge(u,v);
} memset(d,false,sizeof(d));
for(i=;i<=N;++i){
bfs(i);
} flag=true;
for(i=;i<=N&&flag;++i){
for(j=;j<=N&&flag;++j){
if(i==j){
continue;
}
if(d[i][j]||d[j][i]){
continue;
}
flag=false;
break;
}
} if(flag){
printf("Case %d: Kalimdor is just ahead\n",++Case);
}
else{
printf("Case %d: The Burning Shadow consume us all\n",++Case);
} } return ;
}
c2.dfs
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std; #define MAXN 2010
#define MAXM 10010 struct Edge{
int to,next;
}edge[MAXM];
int head[MAXN],tot; void addedge(int u,int v){
edge[tot].to=v;
edge[tot].next=head[u];
head[u]=tot++;
} void init(){
tot=;
memset(head,-,sizeof(head));
} bool d[MAXN][MAXN];//d[i][j]为true表示i可达j
bool vis[MAXN]; void dfs(int t,int t2){
d[t][t2]=true;
vis[t2]=true; int v;
int i;
for(i=head[t2];i!=-;i=edge[i].next){
v=edge[i].to;
if(!vis[v]){
dfs(t,v);
}
} } int main(){ int T;
int N,M;
int u,v;
int i,j;
bool flag;//
int Case=; scanf("%d",&T); while(T--){
scanf("%d%d",&N,&M); init();
for(i=;i<M;++i){
scanf("%d%d",&u,&v);
addedge(u,v);
} memset(d,false,sizeof(d));
for(i=;i<=N;++i){
memset(vis,false,sizeof(vis));
dfs(i,i);
} flag=true;
for(i=;i<=N&&flag;++i){
for(j=;j<=N&&flag;++j){
if(i==j){
continue;
}
if(d[i][j]||d[j][i]){
continue;
}
flag=false;
break;
}
} if(flag){
printf("Case %d: Kalimdor is just ahead\n",++Case);
}
else{
printf("Case %d: The Burning Shadow consume us all\n",++Case);
} } return ;
}
J.Contest Print Server
s.模拟。注意:某个请求没完成的话,要从第一张开始打印(刚开始没细读题,就写成继续打印了)。
ps:when the printed pages counter reached s
这个reached,呵呵,应该是大于吧。
代码写的是当纸张大于等于s时,就更新s并且counter清零的话,wrong了。。
#include<iostream>
#include<stdio.h>
using namespace std; int main(){ int T;
int n,s,x,y,mod;
int i;
char team_name[][];//名字
char str[];
int p[];//需要纸张数
int counter;//当前已输出记数 scanf("%d",&T); while(T--){ scanf("%d%d%d%d%d",&n,&s,&x,&y,&mod); for(i=;i<n;++i){
scanf("%s%s%d%s",team_name[i],str,&p[i],str);
} counter=;
for(i=;i<n;++i){ if(counter+p[i]<=s){//可以打印完
printf("%d pages for %s\n",p[i],team_name[i]);
counter+=p[i];
}
else{//counter+p[i]>s,不能打印完
printf("%d pages for %s\n",s-counter,team_name[i]);
s=(s*x+y)%mod;
counter=; while(p[i]>s){//不能打印完
printf("%d pages for %s\n",s,team_name[i]);
s=(s*x+y)%mod;
counter=;
} printf("%d pages for %s\n",p[i],team_name[i]);
counter+=p[i]; } } printf("\n"); } return ;
}
山东省第四届ACM省赛的更多相关文章
- [原]sdut2624 Contest Print Server (大水+大坑)山东省第四届ACM省赛
本文出自:http://blog.csdn.net/svitter 原题:http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&am ...
- [原]sdut2605 A^X mod P 山东省第四届ACM省赛(打表,快速幂模思想,哈希)
本文出自:http://blog.csdn.net/svitter 题意: f(x) = K, x = 1 f(x) = (a*f(x-1) + b)%m , x > 1 求出( A^(f(1) ...
- Alice and Bob(2013年山东省第四届ACM大学生程序设计竞赛)
Alice and Bob Time Limit: 1000ms Memory limit: 65536K 题目描述 Alice and Bob like playing games very m ...
- 2013年山东省第四届ACM大学生程序设计竞赛-最后一道大水题:Contest Print Server
点击打开链接 2226: Contest Print Server Time Limit: 1 Sec Memory Limit: 128 MB Submit: 53 Solved: 18 [Su ...
- 山东省第四届ACM大学生程序设计竞赛解题报告(部分)
2013年"浪潮杯"山东省第四届ACM大学生程序设计竞赛排名:http://acm.upc.edu.cn/ranklist/ 一.第J题坑爹大水题,模拟一下就行了 J:Contes ...
- sdut Mountain Subsequences 2013年山东省第四届ACM大学生程序设计竞赛
Mountain Subsequences 题目描述 Coco is a beautiful ACMer girl living in a very beautiful mountain. There ...
- Sdut 2409 The Best Seat in ACM Contest(山东省第三届ACM省赛 H 题)(模拟)
题目描述 Cainiao is a university student who loves ACM contest very much. It is a festival for him once ...
- 一场刺激的游戏——很文艺的山东省第四届ACM赛总结(菜鸟版)
人生就像一个个节点,节点中或许有成功,失败,满足,遗憾,但是只要它是不可复制的,在日后,便是美好. ...
- 山东省第三届ACM省赛
Solved ID PID Title Accepted Submit A 2407 Impasse (+) 0 0 B 2415 Chess 0 0 C 2414 An interest ...
随机推荐
- SQL : 在SQL Server 2008(Or Express)中如何Open并编辑数据表【转】
来源:http://www.cnblogs.com/wsdj-ITtech/archive/2011/04/28/2031601.html 通常在SQL Server 2005中,我们可以通过SQL ...
- Advancing The Realtime Web With RethinkDB
RethinkDB is an open-source distributed database built to store JSON and scale with very little effo ...
- Redis持久化机制和恢复机制
Redis持久化方式有两种: (1)RDB 对内存中数据库状态进行快照 (2)AOF 把每条写命令都写入文件,类似mysql的binlog日志 RDB 将Redis在内存中的数据库状态保存到磁盘里面, ...
- mybatis 中的稍微复杂些的sql语句
mybatis 中的稍微复杂些的sql语句: <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYP ...
- WPF性能改善---之化整为零(蜂窝的衍生应用)
在有的项目中,有这样的需求,由于显示器的显示区域是有限的,而软件却要展示一个远大于显示区域的一些元素,此时就要引入放大.缩小.拖动等UI控制技术,而在使用这些技术的同时,在后台有效的控制渲染元素的个数 ...
- 用jquery在必填表单字段前加红星总结
一.总结: 今天公司项目中要求给表单中的必填字段添加标记,因为表单字段比较多,后期又有可能某些字段会有变化,所以写了一段js代码来给表单添加标记. html代码: js代码: 关键步骤: 1.红星的设 ...
- winserver 2008 r2 iis7.5 实现php wordpress url静态化操作步骤(UrlRewrite实现)
参考网址:http://jingyan.baidu.com/article/cbf0e500ebec582eaa2893d2.html 文中涉及到的程序源码以及配置 详见附件:http://files ...
- 剑指offer系列56---连续子数组的最大和
[题目]输入一个整型数组,数组里有正数也有负数.数组中一个或连续多个整数组成一个子数组. * 求所有子数组和的最大值. * [思路]连续求和数组元素.一旦得到的和小于0,就抛弃前面的数组,从当前值重写 ...
- Nexus手动更新索引
如果有耐心的话,完全可以通过在线更新索引的方式来做,但所消耗的时间较长,下面介绍一种简单.可行的方式来手动更新索引文件. 访问http://repo.maven.apache.org/maven2/. ...
- bzoj2152 聪聪可可
Description 聪聪和可可是兄弟俩,他们俩经常为了一些琐事打起来,例如家中只剩下最后一根冰棍而两人都想吃.两个人都想玩儿电脑(可是他们家只有一台电脑)……遇到这种问题,一般情况下石头剪刀布就好 ...