山东省第四届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 ...
随机推荐
- 【转】JavaScript实际应用:父子页面交互
转自:http://blog.csdn.net/xinyueyuli/article/details/509893 最近项目开发中需要子窗口和父窗口交互的内容,基本上无非就是把子窗口的信息传递给父窗口 ...
- css之opacity
设置div元素的不透明级别 语法: value :从0.0(完全透明)到1.0(完全不透明) inherit:应该从父元素继承opacity属性 z-index 属性设置元素的堆叠顺序,仅能在定位元素 ...
- jQuery 追加元素的方法如append、prepend、before
1.jQuery append() 方法 jQuery append() 方法在被选元素的结尾插入内容. 实例 复制代码代码如下: $("p").append("Some ...
- CA接口测试类
package com.creditharmony.adapter.testCase.ca; import org.junit.Test; import com.alibaba.druid.util. ...
- 关于用phonegap+jquery moblie开发 白屏闪屏的解决方法
前几天自己玩开发android应用,做些页面切换效果时,发现两个页面间切换间有白色闪屏的问题. 在网上找了很久的资料,还是没有解决. 最终,发现同事开发的android应用没有这个问题.对比代码排除发 ...
- Winform用匿名方法新建线程的方法
作用:1.将耗时的操作放在单独的线程,加快UI的响应速度.Thread t = new Thread(delegate() { parse.ParseDay(StockCode, FileName); ...
- C#本地时间和GMT(UTC)时间的转换
/// <summary> /// 本地时间转成GMT时间 /// </summary> 4 public static string ToGMTString(DateTime ...
- android学习笔记一——简介
android 是由Andy Rubin创立的一个手机操作系统,后被google收购. google希望同各方共同建立一个标准化.开放式的移动电话软件平台,从而在移动产业内形成了一个开放式的操作平台. ...
- 异常处理:Sys.WebForms.PageRequestManagerParserErrorException:The message……
如果你为了使页面可以达到局部刷新的效果,并且用了UpdatePanel控件,这是如果你在后台页面用到Response对象时肯呢过会抛出一下异常: 解决方法:$(document).ready(func ...
- VS 使用Sql Server 数据库增删改查
/// <summary> /// 执行查询语句,返回DataSet /// </summary> /// <param name="SQLString&quo ...