XJOI NOI2015訓練題7 題解

2021-07-03 06:46:49 字數 3845 閱讀 4953

t1、

原本以為是水題的,但是題目裡有這麼一句話」模1e9+7「。。。。

可以注意到上下左右都要求單調增,那麼狀態就很好確定了

f[i][j]表示第一行放了前i個格仔,第二行放了前j個格仔,並且這些數都是小於等於i+j的

轉義很好寫:f[i][j]可以推給f[i+1][j]和f[i][j+1]。需要時時保證i>j

另外注意此處格仔是否可放。

由於不取模,需要用高精。但是實現只有0.2s

——卡常!

最後還是被卡了20分——本機測試不超時的

訂正的時候發現用long long壓18位居然就能過了,而9位int死活不過。。。。

還有有些人用這個不算開掛嗎?__attribute__((optimize("o2")))

#include #include #include using namespace std;

const long long mod = (1e18);

int a[2][1005];

int n,i,j;

struct bitint

while (ret.a[ret.h]>0) ret.h++;

//for (int i=ret.h;i<70;i++) ret.a[i]=0;

return ret;

} void print()

printf("%lld",a[h-1]);

for (int i=h-2;i>=0;i--)

while (a[i]0)

bool operator

int mult(point p0,point p1,point p2)

void convex_hull()

dw[1] = dot[1]; dw[2] = dot[2]; dwcnt = 2;

for (i=3;i<=n;i++)

for (i=1;i1;i--) dot[++m] = dw[i];}

void find_opp(int i,int &j)}

double mult(point p1,point p2)

double distance(point p1,point p2)

void calc(int i,int j1,int j2)

}}#define fmin(x,y) ( (x)

#define fmax(x,y) ( (x)>(y)?(x):(y) )

const double eps = 1e-12;

void work()

for (i=1;i<=m;i++)

ans = (double)floor(ans*1000) / 1000.;

printf("%.3lf\n",ans);}

int main()

t3、壓軸神題

思路很好

只要我們知道長方形內最高點,最低點,最左點和最右點,預處理這些點之間的上下凸殼就可以合併求答案了。

找最點可以用二分查詢矩形內是否有點在logn的時間內搞定。(我會說我之前求矩形內是否有點寫的是二維樹狀陣列,平白無故多了兩個log然後t得飛起嗎?)

用f1[i][j]表示在點i和點j圍成的矩形內的上凸殼的面積,f2[i][j]表示在點i和點j圍成的矩形內的下凸殼的面積,預處理可以做到o(n^2)

**很呵呵

#include #include #include #include using namespace std;

const int maxn = 3005;

typedef long long ll;

int n,m,q,k,i,j,tx,ty;

int a,b,c,d,a,b,c,d;

int nx,ny,upcnt,dwcnt;

int dw[maxn], up[maxn];

int ax[maxn], ay[maxn];

int sum[maxn][maxn];

ll ans, f1[maxn][maxn], f2[maxn][maxn];

vector ex[maxn], ey[maxn];

struct point

bool operator

for (j--;j>0;j--)

if (dot[i].y>=dot[j].y)

up[1] = i; upcnt = 1;

for (j=i+1;j<=n;j++)

if (dot[i].y>=dot[j].y)

for (j++;j<=n;j++)

if (dot[i].y>=dot[j].y)

dw[1] = i; dwcnt = 1;

for (j=i-1;j>0;j--)

if (dot[i].y<=dot[j].y)

for (j--;j>0;j--)

if (dot[i].y<=dot[j].y)

dw[1] = i; dwcnt = 1;

for (j=i+1;j<=n;j++)

if (dot[i].y<=dot[j].y)

for (j++;j<=n;j++)

if (dot[i].y<=dot[j].y)

}} int find_left(int a,int b,int c,int d)

l = 0; r = ex[t].size()-1;

int ret = 0;

while (l<=r)

l = 0; r = ex[t].size()-1;

int ret = 0;

while (l<=r)

return ret;}

int find_down(int a,int b,int c,int d)

l = 0; r = ey[t].size()-1;

int ret=0;

while (l<=r)

l = 0; r = ey[t].size()-1;

int ret=0;

while (l<=r)

return ret;}

int main()

sort(dot+1,dot+n+1);

sort(ax+1,ax+n+1);

nx = unique(ax+1,ax+n+1)-ax-1;

sort(ay+1,ay+n+1);

ny = unique(ay+1,ay+n+1)-ay-1;

for (i=1;i<=n;i++)

for (i=1;i<=nx;i++)

for (j=1;j<=ny;j++)

sum[i][j] += sum[i-1][j] + sum[i][j-1] - sum[i-1][j-1];

init();

scanf("%d",&q);

while (q--)

if (a>=b || c>=d)

a = find_left(a,b,c,d);

b = find_right(a,b,c,d);

c = find_down(a,b,c,d);

d = find_up(a,b,c,d);

//printf("%d %d %d %d\n",a,b,c,d);

if (a==b || c==d)

ans = f1[a][d] + f1[d][b] + f2[a][c] +f2[c][b];

ans += mult(dot[a], dot[c], dot[d]) + mult(dot[d], dot[c], dot[b]);

printf("%.1lf\n",(double)ans/2.);

} return 0;

}

構造題訓練

由於noip之前沒有怎麼做過構造,導致吃了大虧。構造 互動 基本問題 有一些數,假設有 n 個,有 m 個被標記,我們可以詢問乙個集合。我們可以得知這個集合內是否存在被標記的數。要求次數 o m log 2n 做法1 分治 考慮分治到當前區間 l,r 詢問 l,r 有沒有被標記的數。如果沒有,則返回...

2015第6屆藍橋杯A組第7題 手鍊樣式 題解

題目 手鍊樣式 小明有3顆紅珊瑚,4顆白珊瑚,5顆黃瑪瑙。他想用它們串成一圈作為手鍊,送給女朋友。現在小明想知道 如果考慮手鍊可以隨意轉動或翻轉,一共可以有多少不同的組合樣式呢?請你提交該整數。不要填寫任何多餘的內容或說明性的文字。思路1 dfs 遞迴深度為12 一共的位置 每個位置能選到的種類數為...

藍橋杯真題訓練 2019 2題

2019第二題 小明用字母 a 對應數字 1,b 對應 2,以此類推,用 z 對應 26。對於 27 以上的數字,小明用兩位或更長位的字串來對應,例如 aa 對應 27,ab 對 應 28,az 對應 52,lq 對應 329。請問 2019 對應的字串是什麼?答案提交 這是一道結果填空的題,你只需...