51nod演算法馬拉松13

2022-05-03 23:03:27 字數 4255 閱讀 6235

a 取餘最長路

不難發現路徑可以拆成三條線段,只要知道兩個轉折點的位置就能計算出答案。

設sum(i,l,r)表示第i行從l到r元素的和,則答案可以表示為sum(1,1,x)+sum(2,x,y)+sum(3,y,n)%p。

字首和一下轉化成(s3[n]-s3[y-1])+s2[y]+(s1[x]-s2[x-1])%p,從小到大列舉y,將所有(s1[x]-s2[x-1])扔到乙個集合裡,用個set就能輕鬆實現了。

時間複雜度為o(nlogn)。

#include#include#include#include#include#define rep(i,s,t) for(int i=s;i<=t;i++)

#define dwn(i,s,t) for(int i=s;i>=t;i--)

#define ren for(int i=first[x];i;i=next[i])

using namespace std;

const int buffersize=1<<16;

char buffer[buffersize],*head,*tail;

inline char getchar()

return *head++;

}inline int read()

typedef long long ll;

const int maxn=100010;

ll s1[maxn],s2[maxn],s3[maxn],ans;

sets;

set::iterator it;

int main()

printf("%lld\n",ans);

return 0;

}

b 樹有幾多愁

不難發現這樣幾個性質:

1.節點的編號肯定是按深度遞減的。(可以用相鄰交換法證明)

2.如果知道了葉節點大小的相對順序就能唯一還原出整棵樹的編號。(由性質1不難推出)

那麼我們設f[s]表示將s集合的葉節點都標上號後的答案,因為乘積會很大,所以我們取對數記錄一下方案,最後再乘回去就行了。

然後為了方便轉移隨便dfs算算每種狀態標了多少號就行了,時間複雜度為o(2^c*c+c*n)。

#include#include#include#include#include#define rep(i,s,t) for(int i=s;i<=t;i++)

#define dwn(i,s,t) for(int i=s;i>=t;i--)

#define ren for(int i=first[x];i;i=next[i])

using namespace std;

const int buffersize=1<<16;

char buffer[buffersize],*head,*tail;

inline char getchar()

return *head++;

}inline int read()

typedef long long ll;

const int maxn=100010;

int n,first[maxn],in[maxn],next[maxn<<1],to[maxn<<1],e;

void addedge(int u,int v)

int val[maxn],a[maxn],fa[maxn],pa[maxn],m,dep[maxn];

int s[maxn],vis[maxn],top;

void dfs(int x)

else

} solve((1#include#include#include#include#include#define rep(i,s,t) for(int i=s;i<=t;i++)

#define dwn(i,s,t) for(int i=s;i>=t;i--)

#define ren for(int i=first[x];i;i=next[i])

using namespace std;

const int buffersize=1<<16;

char buffer[buffersize],*head,*tail;

inline char getchar()

return *head++;

}typedef long long ll;

inline ll read()

struct matrix

return c;

} void print()

};void pow(matrix& ans,ll n)

}void solve()

int main()

d 有限揹包計數問題

我們先考慮一種暴力的dp做法:設f[i][j]表示用前i個物品裝滿容量為j的揹包的方案數,然後做個多重揹包就行了,時間複雜度o(n^2)。

我們再來考慮一種暴力的dp做法:設f[i][j]表示用i個物品(不考慮個數限制)裝滿容量為j的揹包的方案數,考慮這i個物品中最小的物品,如果它是1,則f[i][j]+=f[i-1][j-1],否則說明這i個物品均大於1,f[i][j]+=f[i][j-i]。

然後我們發現對於<=sqrt(n)的物品,用第一種做法就行了,對於》sqrt(n)的物品,肯定不會使用超過sqrt(n)個,而且每個物品肯定夠用,用第二種做法就行了。

最後滾動一下陣列把答案合併起來就行了,時間複雜度為o(nsqrt(n))。

#include#include#include#include#include#include#define rep(i,s,t) for(int i=s;i<=t;i++)

#define dwn(i,s,t) for(int i=s;i>=t;i--)

#define ren for(int i=first[x];i;i=next[i])

using namespace std;

const int buffersize=1<<16;

char buffer[buffersize],*head,*tail;

inline char getchar()

return *head++;

}inline int read()

const int maxn=100010;

const int mod=23333333;

typedef long long ll;

int n;

int f[2][maxn],g[2][maxn],g2[maxn],sum[maxn];

int main()

rep(a,0,n) (ans+=(ll)g2[a]*f[cur][n-a])%=mod;

printf("%lld\n",ans);

} return 0;

}

e b君的**

我們可以設f[x][s]表示當前在x節點,已走過狀態為s,期望再走幾步才能結束整個過程。

直接暴力消元肯定是不行的,但我們按s分一下層,做512次消元再壓一下常數就行了。

時間複雜度為o(2^c*n^3)。

#include#include#include#include#include#include#define rep(i,s,t) for(int i=s;i<=t;i++)

#define dwn(i,s,t) for(int i=s;i>=t;i--)

#define ren for(int i=first[x];i;i=next[i])

using namespace std;

const int buffersize=1<<16;

char buffer[buffersize],*head,*tail;

inline char getchar()

return *head++;

}inline int read()

const int maxn=55;

const double eps=1e-12;

typedef double matrix[maxn][maxn];

const int maxm=550;

int n,m,s,x[9],e[maxn][maxn];

void gauss(matrix& a)

matrix a;

int main()

rep(i,0,8) x[i]=read();s=read();

dwn(s,511,0)

} printf("%.6lf\n",f[s][0]);

return 0;

}

51nod演算法馬拉松32

比賽鏈結 馬拉松是真的難 應該是我太菜了tnt 同bzoj1534 題解戳這裡 n個有標號的點,其中m個是葉子節點。問有多少數的形態。include include include include include using namespace std typedef long long ll co...

51nod演算法馬拉松15

智力徹底沒有了。看來再也拿不到獎金了qaq。a b君的遊戲 因為資料是9b1l,所以我們可以hash試一下資料。include include include include define rep i,s,t for int i s i t i define dwn i,s,t for int i ...

51nod 演算法馬拉松18 總結

第一次打馬拉松。a 一看題。什麼鬼。n 4竟然是無解,第乙個點給了乙個n 5的,好像是構造的挺有規律的樣子。那就偶數無解,奇數照著他的構造方法寫一發吧。怎麼a了?不管了。既然結束了還是要回來好好想一下是什麼情況的。偶數肯定是無解的,因為一共有n n 1 2 條邊,那麼每種顏色的邊出現次數相等的話,就...