H题成功拿到HDU statistic rank1!(我TM是有多闲。。)
已经完成赛后AK!可喜可贺!虽然这个AK的周期略长。。都是我太弱。。
非常神奇的一场比赛,两百多个队在一个体育馆(羽毛球馆)内比赛,两桌距离不超过半米。自己的桌牌在别人的电脑后面,直接导致我们对面的队一开始直接坐了我们的位置。正式比赛还拿了我们的题。。。
首先,题目直接在比赛前放在了桌上。没有信封!
tomriddly直接抄起了题看了一眼,发现是题,就扣下了!但是这一瞬间就读完了A题题意!然后!然后!在调试Eclipse的时候!写完了A题。
结果。
结果。
并没有拿到runid 1
交上去已经runid 14了
然后,
就没有然后了。
A题 求2的n次方,要用高精度。
B题 给一个n*m的考场,有一些位置不能坐人,每个人能看到左右以及左前方右前方的人的试卷。(类似于国际象棋棋盘上放最多的兵),二分图即可。
C题 有n道题,给出每道题通过的人数,问过了C道题及以上的人最多有多少。
这题我们当时没有想到正解。其实要想每个人都过题多,只要尽量使得每人过题数尽量平均即可。这时候可以想到二分总人数,来验证答案。再更新一个最大值即可。
jiefangxuanyan
一开始就瞄上了J题,然后以迅雷不及掩耳之势算出了公式,成功1Y拿下一血和一个很胖的一血气球(志愿者发气球的时候还砸到了对面的同学的脑袋,简直了)。然后看到榜上E过了好多,于是tomriddly
就写了E,然后1Y。然后jiefangxuanyan
刷刷刷敲了B题,是个模拟。然后我们觉得D应该是一个线段树,在解决了longlong*longlong
的问题之后(汇编乘法挂,详情请问本人),tomriddly
一顿敲,直到觉得自己写不出像样的lazy
标记。。
这时znl1087
和jiefangxuanyan
发现F是个脑筋急转弯。。。。
然后把tomriddly
赶下键盘,jiefangxuanyan
成功使用java获得1Y
然后是一个漫长的空键盘阶段,将近一个小时。。当时场上一部分人过了G题,一部分人过了A,有几个人过了D。然后开始每个人轮流想这几道题。。在一个小时之后,tomriddly
想出了G的做法。虽然znl1087
和jiefangxuanyan
都没听明白,但是本着不让键盘空着(虽然TMD已经空了一个小时)的原则,让他上去写了。好久之后(其实就是他写了好久好久,调了好久好久,期间还上了一个大号),写完了,但是WA了。这个时候jiefangxuanyan
成功推出A题公式。。然后上键盘微调1Y。然后tomriddly
惊奇的发现自己的程序居然写的是int dfs(xxxxx)
说好的long long
呢!
然后过了。此时大概还有一个半小时。然后tomriddly
说我们一定还要再过一题!我们俩很认同的点了点头。然后三个人同时想D。
然后jiefangxuanyan
感觉这个巨大的MOD有一些奇怪,应该有一些奇怪的性质。。znl1087
提出,可能会出现循环。然后用python
打了个表。居然真TM有循环,并且经过测试,30次以内必出!
于是,去掉lazy,特别简单的线段树,1Y(当然是开了某个挂的)
然后已经A了7题,还剩48分钟。估计了一下排名,大概金牌是稳了。。于是tomriddly
劝告我们,再做一题就赚了!不然也不亏(废话)
于是大家一起找I题的规律。。。。
然而并没有找出来。。。。
然后比赛就结束了。。。。。
赛前我们三个人讨论了一下当天的午饭会发啥,tomriddly
预测应该会比省赛四省赛的时候工大发的好。znl1087
根据赛场布置风格推测,估计连马可波罗肠都没有。。。结果。。。结果。。。
奶茶加面包。。。。
没了。。
没了。。
DRD经常使用一个文本处理软件,这个软件每输入一个字符就有一定的概率(p)崩溃,并且丢失上次保存之后的所有数据。执行一次保存需要x字符的代价(但是不会崩溃)问在最优策略下,输入字符的期望是多少
首先考虑一次性完成i个字符输入的期望e[i]
。发现是一个近似的等比数列。根据推出来的公式,每次保存之间的间隔尽量平均是最优解。预处理出e[i]
,然后枚举保存的次数,O(1)计算出期望,取期望最小的值为答案。
HDU5236,注意这题没有special judge,不写%.6f输出会WA
/* written by jiefangxuanyan */
#include
#include
#include
#include
const int N=110000;
double t[N];
int main(){
int cn;
scanf("%d",&cn);
for(int ci=1;ci<=cn;ci++){
int n;
double fail;
int save;
scanf("%d%lf%d",&n,&fail,&save);
t[0]=0;
for(int i=1;i<=n;i++){
t[i]=(t[i-1]+1)/(1-fail);
}
t[n+1]=0;
double s=DBL_MAX;
for(int k=1;k<=n;k++){
int left=n%k;
s=std::min(t[n/k+1]*left+t[n/k]*(k-left)+save*k,s);
}
printf("Case #%d: %.6f\n",ci,s);
}
return 0;
}
base64编码
,对一个字符串进行n次base64编码
,输出答案。
同上。。
hdu5237
/* written by tomriddly */
#include
using namespace std;
string Encode(const char* Data,int DataByte)
{
//编码表
const char EncodeTable[]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
//返回值
string strEncode;
char Tmp[4]= {0};
int LineLength=0;
for(int i=0; i<(int)(DataByte / 3); i++)
{
Tmp[1] = *Data++;
Tmp[2] = *Data++;
Tmp[3] = *Data++;
strEncode+= EncodeTable[Tmp[1] >> 2];
strEncode+= EncodeTable[((Tmp[1] << 4) | (Tmp[2] >> 4)) & 0x3F];
strEncode+= EncodeTable[((Tmp[2] << 2) | (Tmp[3] >> 6)) & 0x3F];
strEncode+= EncodeTable[Tmp[3] & 0x3F];
}
//对剩余数据进行编码
int Mod=DataByte % 3;
if(Mod==1)
{
Tmp[1] = *Data++;
strEncode+= EncodeTable[(Tmp[1] & 0xFC) >> 2];
strEncode+= EncodeTable[((Tmp[1] & 0x03) << 4)];
strEncode+= "==";
}
else if(Mod==2)
{
Tmp[1] = *Data++;
Tmp[2] = *Data++;
strEncode+= EncodeTable[(Tmp[1] & 0xFC) >> 2];
strEncode+= EncodeTable[((Tmp[1] & 0x03) << 4) | ((Tmp[2] & 0xF0) >> 4)];
strEncode+= EncodeTable[((Tmp[2] & 0x0F) << 2)];
strEncode+= "=";
}
return strEncode;
}
int n;
string a;
int main()
{
int fuck;
scanf("%d", &fuck);
for (int cas = 1; cas <= fuck; cas++)
{
cin >> n >> a;
for (int i = 1; i <= n; i++)
a = Encode(a.c_str(), a.length());
cout << "Case #" << cas << ": " << a << endl;
}
return 0;
}
给出一个计算的序列,包含{+,*,^}
三种运算。给出两种操作,1是给出初始值,求按照序列计算的答案,2是修改序列中某个位置的数和运算符。
比赛的时候没想出来,比完赛想出来了。首先题目中,用来MOD的值是一个比较小的数,所以大概思路是把一个区间的运算维护成一个a[mod]
大小的映射。但是mod = 29393
貌似又太大,于是想到把29393 = 7 * 13 * 17 * 19
,然后分别维护这四个因数的线段树,然后利用中国剩余定理算出最后答案。维护区间用线段树去实现,可以把映射单独写成一个数据结构,然后开这个数据结构的线段树。
单点修改,并且只查询根节点,线段树操作非常简单。
jiefangxuanyan
写代码的时候碰到一些细节问题,不过比赛的时候队友在旁边看,肯定不会出现这些问题的。
HDU5238
/* written by jiefangxuanyan */
#include
#include
#include
template<int base>
class Mapping{
int tgt[base];
public:
int &operator[](int pos){
return tgt[pos];
}
void clear(){
for(int i=0;i int a){
for(int i=0;i %base;
}
}
void setMul(int a){
for(int i=0;i *a)%base;
}
}
void setPow(int a){
for(int i=0;i 1;
int cur=i;
for(int p=a;p;p>>=1){
if(p&1){
tgt[i]=(tgt[i]*cur)%base;
}
cur=(cur*cur)%base;
}
}
}
void combine(Mapping &a,Mapping &b){
for(int i=0;i int N=55000;
int mask;
template<int base>
class SegTree{
static const int SZ=4*N;
Mapping data[SZ];
static int left(int a){
return a<<1;
}
static int right(int a){
return left(a)|1;
}
void update(int a){
for(a>>=1;a;a>>=1){
data[a].combine(data[left(a)],data[right(a)]);
}
}
public:
void clear(){
for(int i=0;iint pos,int a){
pos|=mask;
data[pos].setAdd(a);
update(pos);
}
void setMul(int pos,int a){
pos|=mask;
data[pos].setMul(a);
update(pos);
}
void setPow(int pos,int a){
pos|=mask;
data[pos].setPow(a);
update(pos);
}
int get(int a){
a%=base;
return data[1][a];
}
};
SegTree<7> _7;
SegTree<13> _13;
SegTree<17> _17;
SegTree<19> _19;
int inv(int a,int m){
return a==1?1:inv(m%a,m)*(m-m/a)%m;
}
int main(){
const int M=7*13*17*19;
const int MA=M/7,MB=M/13,MC=M/17,MD=M/19;
const int A=MA*inv(MA%7,7),
B=MB*inv(MB%13,13),
C=MC*inv(MC%17,17),
D=MD*inv(MD%19,19);
int cn;
scanf("%d",&cn);
for(int ci=1;ci<=cn;ci++){
printf("Case #%d:\n",ci);
_7.clear();
_13.clear();
_17.clear();
_19.clear();
int n,m;
scanf("%d%d",&n,&m);
mask=1;
while(mask<=n){
mask<<=1;
}
for(int i=0;iint a;
scanf(" %c%d",&op,&a);
if(op=='+'){
_7.setAdd(i,a);
_13.setAdd(i,a);
_17.setAdd(i,a);
_19.setAdd(i,a);
} else if(op=='*'){
_7.setMul(i,a);
_13.setMul(i,a);
_17.setMul(i,a);
_19.setMul(i,a);
} else if(op=='^'){
_7.setPow(i,a);
_13.setPow(i,a);
_17.setPow(i,a);
_19.setPow(i,a);
}
}
for(int i=0;i<m;i++){
int type;
scanf("%d",&type);
if(type==1){
int a;
scanf("%d",&a);
printf("%d\n",(A*_7.get(a)+B*_13.get(a)+C*_17.get(a)+D*_19.get(a))%M);
} else if(type==2){
int pos;
char op;
int a;
scanf("%d %c%d",&pos,&op,&a);
pos--;
if(op=='+'){
_7.setAdd(pos,a);
_13.setAdd(pos,a);
_17.setAdd(pos,a);
_19.setAdd(pos,a);
} else if(op=='*'){
_7.setMul(pos,a);
_13.setMul(pos,a);
_17.setMul(pos,a);
_19.setMul(pos,a);
} else if(op=='^'){
_7.setPow(pos,a);
_13.setPow(pos,a);
_17.setPow(pos,a);
_19.setPow(pos,a);
}
}
}
}
return 0;
}
给出n个数和一个初始值为0的答案。每次操作给出一个区间[l,r]
,把区间所有的数加到答案中,之后把区间的每个数都平方。每次操作都需要输出答案 mod 9223372034707292160(2 ^ 63 - 2 ^ 31)
首先,想到这个题可以用线段树来维护区间的和,然后对于(2 ^ 63 - 2 ^ 31)
这个数,我们发现了一些神奇的性质,即任意数的平方MOD此数,重复操作至多29次就会进入一个不变的数。因此,可以在线段树维护时,直接限定次数。具体做法是维护每个区间中更新次数最少的数量,如果发现更新次数等于30就不往下更新,否则继续往下更新。
HDU 5239
/*************************************************************************
> File Name: pd.cpp
> Author: tomriddly
> Created Time: 三 5/27 05:45:39 2015
************************************************************************/
#include
using namespace std;
typedef unsigned long long ll;
const ll MOD = 9223372034707292160LL;
const int MAXN = 111111;
int n, m, cnt[MAXN << 2];
ll tree[MAXN << 2], a[MAXN];
inline ll mulmod(ll x, ll y, ll mod)
{
ll ret = 0;
__asm__("movq %1,%%rax\n imulq %2\n idivq %3\n":"=d"(ret):"m"(x),"m"(y),"m"(mod):"%rax");
return ret;
}
#define lx (x << 1)
#define rx (lx | 1)
#define mid ((l + r) >> 1)
inline void pushup(const int &x)
{
tree[x] = (tree[lx] + tree[rx]) % MOD;
cnt[x] = min(cnt[lx], cnt[rx]);
}
inline void build(const int &x, const int &l, const int &r)
{
if (l == r)
{
tree[x] = a[l];
cnt[x] = 0;
return ;
}
build(lx, l, mid);
build(rx, mid + 1, r);
pushup(x);
}
inline ll query(const int &x, const int &l, const int &r, const int &ql, const int &qr)
{
if (l == ql && r == qr)
return tree[x];
if (mid >= qr)
return query(lx, l, mid, ql, qr);
if (mid < ql)
return query(rx, mid + 1, r, ql, qr);
return (query(lx, l, mid, ql, mid) + query(rx, mid + 1, r, mid + 1, qr)) % MOD;
}
inline void modify(const int &x, const int &l, const int &r, const int &ql, const int &qr)
{
if (cnt[x] == 30)
return ;
if (l == ql && r == qr && l == r)
{
tree[x] = mulmod(tree[x], tree[x], MOD), cnt[x]++;
return ;
}
if (mid >= qr)
modify(lx, l, mid, ql, qr);
else if(mid < ql)
modify(rx, mid + 1, r, ql, qr);
else
{
modify(lx, l, mid, ql, mid);
modify(rx, mid + 1, r, mid + 1, qr);
}
pushup(x);
}
int main()
{
int fuck;
scanf("%d", &fuck);
for (int cas = 1; cas <= fuck; cas++)
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
scanf("%I64d", a + i);
build(1, 1, n);
printf("Case #%d:\n", cas);
ll ans = 0;
while (m--)
{
int l, r;
scanf("%d%d", &l, &r);
ans = (ans + query(1, 1, n, l, r)) % MOD;
modify(1, 1, n, l, r);
printf("%I64d\n", ans);
}
}
return 0;
}
有n门考试,每场考试有需要复习的时间,开始时间及持续时间。可以在非连续的时间复习,考试时不能复习。问能否通过全部的考试。
从前往后直接模拟,按照考试顺序复习,判断能否完成即可。
HDU5240
/* written by tomriddly */
#include
using namespace std;
const int MAXN = 111111;
struct Fuck
{
long long r, s, t;
inline void get()
{
scanf("%I64d%I64d%I64d", &r, &s, &t);
t += s;
}
inline friend bool operator <(const Fuck &x, const Fuck &y)
{
return x.s < y.s;
}
}a[MAXN];
int n;
int main()
{
int fuck;
scanf("%d", &fuck);
for (int cas = 1; cas <= fuck; cas++)
{
scanf("%d", &n);
for (int i = 1; i <= n; i++)
a[i].get();
sort(a + 1, a + 1 + n);
int i = 1, j = 1;
long long rest = a[1].s;
bool haveans = true;
while (i <= n)
{
if (rest < a[i].r)
{
if (i == j)
{
haveans = false;
break;
}
a[i].r -= rest;
j++;
rest = a[j].s - a[j - 1].t;
}
else
{
rest -= a[i].r;
i++;
}
}
printf("Case #%d: ", cas);
if (!haveans)
puts("NO");
else
puts("YES");
}
return 0;
}
Mike和他的朋友们喜欢学习语言。然后Mike是最DIAO的,他会n门语言,而他的朋友们会的都是他的子集。且彼此之间有如下关系:
。。。。。。。。。。。谁是谁的超集之类的。。。。。。
好多关系
不想写了。。。。。。虽然并没有什么卵用。。。
求满足这些条件的集合种数
以为是拓扑排序,树形DP。。。
结果后来发现每种语言之间是独立的。。
所以答案肯定是k^n。。。
通过sample input and sample output发现。。
k = 32。。java过之。。
HDU5241
/* written by tomriddly */
import java.util.*;
import java.math.*;
public class Main
{
static public void main(String[]args)
{
Scanner cin = new Scanner(System.in);
int fuck = cin.nextInt();
for (int cas = 1; cas <= fuck; cas++)
{
int n = cin.nextInt();
System.out.printf("Case #%d: ", cas);
System.out.println(BigInteger.valueOf(32).pow(n));
}
cin.close();
}
}
一棵树有n个节点,每个节点有一个价值。一个人从根节点走到某叶子节点算一次游戏,可以获得经过节点的所有价值。但每个节点的价值只能被获得一次。问在同一棵树上进行K次游戏,最多能获得多少价值。
对于每个节点,统计从这个点走到根节点能获得的价值之和。一次DFS搞定。把这些节点按照这个和从大到小排序。按照这个顺序,再次统计到根节点的价值之和,再次DFS。这次把已经走过的节点价值设为0。按照这次统计的和进行排序。然后从前往后取K次,每次用dfs把叶子节点到根节点的一条链拿干净,不重复拿取。统计价值之和,即为答案。
证明略。。
HDU5242
/*************************************************************************
> File Name: pg.cpp
> Author: tomriddly
> Created Time: 三 5/27 05:15:42 2015
************************************************************************/
#include
using namespace std;
const int MAXN = 111111;
long long a[MAXN];
int n, m, pos[MAXN];
bool vis[MAXN];
struct Arc
{
int dest;
Arc *next;
inline Arc() {}
inline Arc(const int &dest, Arc *next):dest(dest), next(next) {}
}Npool[MAXN], *Nptr, *adj[MAXN];
struct Fuck
{
int i;
long long sum;
inline friend bool operator <(const Fuck &x, const Fuck &y)
{
return x.sum > y.sum;
}
}s[MAXN];
inline void insert(const int &start, const int &finish)
{
adj[start] = new(Nptr++)Arc(finish, adj[start]);
}
inline long long dfs(const int &x)
{
if (s[x].sum)
return s[x].sum;
s[x].sum = a[x];
for (Arc *p = adj[x]; p; p = p->next)
s[x].sum += dfs(p->dest);
return s[x].sum;
}
inline long long dfs2(const int &x)
{
if (s[pos[x]].sum)
return 0;
s[pos[x]].sum = a[x];
for (Arc *p = adj[x]; p; p = p->next)
s[pos[x]].sum += dfs2(p->dest);
return s[pos[x]].sum;
}
inline void dfs3(const int &x)
{
if (vis[pos[x]])
return ;
vis[pos[x]] = true;
for (Arc *p = adj[x]; p; p = p->next)
dfs3(p->dest);
}
int main()
{
int fuck;
scanf("%d", &fuck);
for (int cas = 1; cas <= fuck; cas++)
{
Nptr = Npool;
memset(adj, 0, sizeof(adj));
memset(s, 0, sizeof(s));
memset(vis, false, sizeof(vis));
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
{
scanf("%I64d", a + i);
s[i].i = i;
}
for (int i = 1; i < n; i++)
{
int u, v;
scanf("%d%d", &u, &v);
insert(v, u);//因为是从叶子节点向上计算,所以反向建边
}
for (int i = 1; i <= n; i++)
if (!s[i].sum)
dfs(i);
sort(s + 1, s + 1 + n);
for (int i = 1; i <= n; i++)
s[i].sum = 0, pos[s[i].i] = i;
for (int i = 1; i <= n; i++)
if (!s[i].sum)
dfs2(s[i].i);
sort(s + 1, s + 1 + n);
for (int i = 1; i <= n; i++)
pos[s[i].i] = i;
long long ans = 0;
int cnt = 0;
for (int i = 1; i <= n && cnt < m; i++)
if (!vis[i])
{
dfs3(s[i].i);
ans += s[i].sum, cnt++;
}
printf("Case #%d: %I64d\n", cas, ans);
}
return 0;
}
题意比较复杂。。不想说。。直接讲做题过程。。
这道题是一道没那么难的计算几何。。。裸半平面交。。
当时比赛没看完全是跟着榜了。。要是比赛的时候看了就能过了。。
作为只有AK队过的题,一直以为很难。其实如果不限内存的话挺好过的。
HDU上面这道题的内存限制是丧病的32M,如果开100W的double,开几个就直接爆了。。
大概是我比较2。。。没想到怎么优化内存,一直MLE
要是比赛的时候写了就好了,,不限内存。。。
最后过的方法是,把Line结构体里的Point用short记录输入的点的索引,从而节省好几个double的空间。。
然后就过了。。时间HDUrank1!(其实关云长是我在VJ上交的。。)
对于给定的所有点,求出任意两个点之间的直线两侧的点的个数。如果某条直线单侧的点的个数小于[n/3],那么就把这条直线放入一个vector中存下来。全部扫一遍,把这些直线做一遍半平面交,算一下面积就行了。注意扫的方法,枚举每个点作为中心点,跟其他点连线,然后按照极角排序。用队列维护,扫一圈就可以把值统计出来了。
HDU5243
/*************************************************************************
> File Name: ph.cpp
> Author: znl1087
> Mail: [email protected]
> Created Time: 一 6/ 1 21:22:30 2015
************************************************************************/
#include
#include
#include
#include
#include
#include
using namespace std;
int n;
int tcnt;
struct Point{
double x,y;
Point(double x=0,double y=0):x(x),y(y){}
}in[1005];
typedef Point Vec;
//向量+向量 = 向量,点+向量 = 点
Vec operator +(Vec A,Vec B){return Vec(A.x+B.x,A.y+B.y);}
//点-点 = 向量
Vec operator -(Point A,Point B){return Vec(A.x-B.x,A.y-B.y);}
//向量*数 = 向量
Vec operator *(Vec A,double p){return Vec(A.x*p,A.y*p);}
//向量/数 = 向量
Vec operator /(Vec& A,double p){return Vec(A.x/p,A.y/p);}
bool operator <(const Point& a,const Point& b){
return a.xconst double EPS = 1e-7;
int dcmp(double x){
if(fabs(x)return 0;else return x<0? -1: 1;
}
bool operator == (const Point& a,const Point &b){
return dcmp(a.x-b.x)==0 &&dcmp(a.y-b.y) == 0;
}
double ang(Vec v){return atan2(v.y,v.x);}
/*==========以上为基本定义============*/
double Dot(Vec& A,Vec& B){return A.x*B.x+A.y*B.y;}
double Length(Vec& A){ return sqrt(Dot(A,A));}
double Angle(Vec& A,Vec& B){return acos(Dot(A,B)/Length(A)/Length(B));}
/*==========用点积算向量长度和两个向量夹角============*/
double Cross(Vec A,Vec B){return A.x*B.y - A.y*B.x;}
double PolygonArea(vector & p){
int n = p.size();
double area = 0;
for(int i=1;i1;i++)
area += Cross(p[i] - p[0],p[i+1]-p[0]);
return fabs(area/2);
}
struct Line{
short P1;
short P2;
double ang;
short left;
Line(){}
Line(short p1,short p2){
P1 = p1,P2 = p2;
Vec v = in[p2]-in[p1];
ang = atan2(v.y,v.x);left = 0;}
bool operator < (const Line& L) const {
return ang < L.ang;
}
Vec getV(){
return in[P2]-in[P1];
}
Point getP(){
return in[P1];
}
};
vector fuck;
Line temp[1005];
bool OnLeft(Line L,Point P){
return dcmp(Cross(L.getV(),P - L.getP()))>=0; //如果线上的点不算就改成>
}
Point GetIntersection(Line& a, Line& b){
Vec u = a.getP() - b.getP();
double t = Cross(b.getV(),u)/Cross(a.getV(),b.getV());
return a.getP()+a.getV()*t;
}
int HalfplaneIntersection(vector & L,vector & poly){
int n = L.size();
sort(L.begin(),L.end());
int first,last;
Point *p = new Point[n];
Line *q = new Line[n];
q[first = last = 0] = L[0];
for(int i=1;iwhile(first1]))last--;
while(firstif(fabs(Cross(q[last].getV(),q[last-1].getV()))if(OnLeft(q[last],L[i].getP()))q[last] = L[i];
}
if(first1] = GetIntersection(q[last-1],q[last]);
}
while(first1]))last -- ;
if(last-first<=1){
delete[] p;
delete[] q;
return 0;
}
p[last] = GetIntersection(q[last],q[first]);
int m = 0;
for(int i=first;i<=last;i++)poly.push_back(p[i]),m++;
delete[] p;
delete[] q;
return m;
}
/*=========半平面交所需函数及主过程=========*/
int main(){
//freopen("in.txt","r",stdin);
int T;
cin>>T;
for(int cas = 1;cas <= T;cas++){
vector poly;
scanf("%d",&n);
double x,y;
poly.clear();
fuck.clear();
for(int i=0;iscanf("%lf%lf",&x,&y);
in[i] = Point(x,y);
}
int limit = (int)floor(n/3.0);
for(short i=0;i0;
queue q;
for(short j=0;jif(i!=j)
temp[tcnt++] = Line(i,j);
sort(temp,temp+tcnt);
int len = tcnt,u = 0;
for(int k=0;kif(k){
q.pop();
u--;
}
for(;dcmp(Cross(temp[k].getV(),temp[(k+u)%len].getV()))>=0 && u for(int k=0;kif(n - temp[k].left - 1 < limit)
fuck.push_back(temp[k]);
}
//for(int k=0;k
// Point a = fuck[k].P,b = a+fuck[k].v;
// printf("x1: %f y1: %f x2:%f y2:%f\n",a.x,a.y,b.x,b.y);
//}
//printf("%d\n",fuck.size());
}
int ok = HalfplaneIntersection(fuck,poly);
printf("Case #%d: %.6f\n",cas,ok?PolygonArea(poly):0);
}
return 0;
}
给出一组a[i]
,可以根据某种规则,把这个数组加密成b[i]
。然后给出b[i]
,要求求出所有a[i]
。
比赛时利用__builtin_parity()
打表,发现给定的矩阵是一个递归构成的矩阵,把这个矩阵等分成四份,右上角是-x子矩阵,其他的三份都是x子矩阵。a*[] = b
,所以我们只要找到一种操作,利用行初等变换把矩阵变换成单位矩阵,这样b经过同样的变换后得到的就是a。
找规律大法好!jiefangxuanyan
线代学的就是好!
HDU5244
/*************************************************************************
> File Name: pi.cpp
> Author: jiefangxuanyan
> Created Time: 四 5/28 12:32:42 2015
************************************************************************/
#include
long long in[1<<20];
void sp(long long *t,int n){
if(n==1){
return;
}
int m=n>>1;
for(int i=0;ifor(int i=0;ifor(int i=0;i1];
}
for(int i=0;i>=1;
}
for(int i=0;i/*for(int i=0;i
sp(t,m);
sp(t+m,m);
}
int main(){
int cn;
scanf("%d",&cn);
for(int ci=1;ci<=cn;ci++){
int k;
scanf("%d",&k);
int n=1<for(int i=0;i"%I64d",in+i);
}
sp(in,n);
printf("Case #%d:",ci);
for(int i=n-1;i>=0;i--){
printf(" %I64d",in[i]);
}
putchar('\n');
}
return 0;
}
在一个n*m的矩阵上随机选取k个小的矩形区域覆盖,求被覆盖的格子的数量的数学期望。随机是指从矩阵中随机选取两个格子,作为矩形的两个顶角。
这题的数学期望等于每个格子被覆盖的概率之和。所以只需要求每个格子被覆盖的概率即可。可以算出,一次随机覆盖,每个格子不被覆盖的概率p,这样,1-p^k就是这个格子被覆盖的概率。求和即可。
HDU 5245
/*************************************************************************
> File Name: pj.cpp
> Author: znl1087
> Mail: [email protected]
> Created Time: 三 5/27 04:44:07 2015
************************************************************************/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
int main(){
int T;
cin>>T;
int m,n,k;
for(int cas = 1;cas <= T;cas++){
scanf("%d%d%d",&m,&n,&k);
double ans = 0;
for(int i=1;i<=m;i++)
for(int j=1;j<=n;j++){
double t = (1.0 - ((i-1)*(i-1)+(m-i)*(m-i)) /(double) (m * m))
* (1.0-((j-1) * (j-1) + (n-j) * (n-j)) / (double)(n * n));
//printf("%lf\n",t);
ans += 1.0-pow(1.0-t,(double)k);
}
//printf("%f\n",ans);
printf("Case #%d: %d\n",cas,(int)round(ans));
}
return 0;
}
B题E题是水题,F题是一个脑筋急转弯,A题和J题是概率题,G题是一道不错的贪心,CD应该都是带一些数论的线段树。。I题是找规律加矩阵初等变换。。。 H题没看,不知道是啥,全场只有AK队过了。 H题就是个计算几何,半平面交,比赛时候不限内存。。要是直接做应该能过。。是我没读题。。总体来说,数学题偏多,题目质量还可以。基本上能做出J题的都能拿到奖,G题是铜牌和银牌的分界题,A,C,D,I,任意做出两个就是金牌。(AK队太叼,不敢评价)。1个AK,7个八题,9个七题,都是金牌。我们队这次基本都是1Y,自我感觉还是可以的。中间空了一个小时的键盘是硬伤,需要继续努力训练,并且好好总结自己的问题。