泉州集训之HSY的day1
生活随笔
收集整理的這篇文章主要介紹了
泉州集训之HSY的day1
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
國慶泉州集訓day1day1day1
寫博客前的吐槽:
題面可以說是發揮了出題人所有的想象力了
emmmm
題目背景真是有趣
T1:HSYHSYHSY的質數
emmmm基礎數論
裸的線性篩法,注意只要求質數的個數,那我們線性篩選的時候就不用把每個質數都標記出來,我們只需要記錄質數的個數即可
稍微改改線性篩法的板子即可
Code:
#include<iostream> #include<cstdio> #include<cstring> #define size 10000010using namespace std;long long pri[size]; int tot,f[size]; //f[i]表示1~i的質數個數 //線性篩法 void prepare(int n) {memset(pri,1,sizeof(pri));pri[1]=0;for(int i=2;i<=n;i++){if(pri[i]){f[i]++;for(int j=2;j<=n/i;j++)pri[i*j]=0;//篩質數 for(int j=1;j<=i&& i*j<=n;j++)if(pri[j]) f[j*i]++;//處理題目要求的特殊情況}} }int main() {prepare(1e7);for(int i=1;i<=size;i++)f[i]+=f[i-1];//累加前綴和int q;scanf("%d",&q);while(q--){long long l,r;scanf("%lld%lld",&l,&r);printf("%d\n",f[r]-f[l-1]);//前綴和的小應用 }return 0; }T2:HSYHSYHSY的密室
emmmm
狀壓+最短路可以A掉
然后其實BFS就可以過…
因為邊權都是1…
至于如何狀壓和為何狀壓…
首先數據范圍 k<=10k<=10k<=10 這就很明顯了
然后我們按照正常思路去處理這些鑰匙的話,是很難實現的
所以狀壓可以搞一搞
-
用二進制去記錄房間每種鑰匙的數量
-
通過 aaa&bbb=aaa的方法判定是否可以通過
-
通過 a∣ba|ba∣b的方式獲得該房間內的鑰匙
spfa Code:
#include<iostream> #include<cstdio> #include<cstring> #include<queue>using namespace std;const int INF=0x7ffffff; const int N=6000;int room[N],d[N][1<<10]; bool vis[N][1<<10]; int n,m,k,head[N],ver[N*2],Next[N*2],tot,edge[N];struct fengzi {int x,num; };void add(int x,int y,int z) {ver[++tot]=y;Next[tot]=head[x];edge[tot]=z;head[x]=tot; }void spfa() {queue<fengzi> qwq;for (int i = 1; i <= n; i++) for(int j=0;j<(1<<k);j++)d[i][j]=INF;fengzi now;now.x=1;now.num=room[1];vis[1][room[1]]=1;d[1][room[1]]=0;qwq.push(now);while(!qwq.empty()){fengzi QwQ=qwq.front();qwq.pop();int x=QwQ.x,num=QwQ.num;vis[x][num]=0;for(int i=head[x];i;i=Next[i]){int y=ver[i];if((edge[i] & num)==edge[i])//如果鑰匙數量符合 {int res=num | room[y]; //累加鑰匙 if(d[y][res]>d[x][num]+1){d[y][res]=d[x][num]+1;if(!vis[y][res]){vis[y][res]=1;fengzi pwp;pwp.x=y;pwp.num=res;qwq.push(pwp);}}}}} }int main() {scanf("%d%d%d",&n,&m,&k);for(int i=1;i<=n;i++){int res=0;for(int j=1;j<=k;j++){int t;scanf("%d",&t);res=(res<<1)+t;//狀壓處理方式 }room[i]=res;}for(int i=1;i<=m;i++){int x,y,res=0;scanf("%d%d",&x,&y);for(int j=1;j<=k;j++){int t;scanf("%d",&t);res=(res<<1)+t;//狀壓處理方式 }add(x,y,res);}spfa();int ans=INF;for(int i=0;i<(1<<k);i++)ans=min(ans,d[n][i]);if(ans==INF) puts("No Solution");else printf("%d\n",ans);return 0; }T3:HSYHSYHSY的佛光
隱藏起來的LCA…
手推一推即可發現規律…
-
1.其實題目就是在求從AAA到BBB和從CCC到AAA的重復路徑
-
2.畫圖找規律
假設AAA和BBB的LCALCALCA是L1L_1L1?,那我們可以發現從L1L_1L1?出發,到A和和和B$的路徑是不相交的
依次類推,我們假設BBB和CCC的LCALCALCA是L2L_2L2?,假設AAA和CCC的LCALCALCA是L3L_3L3?
那么我們可以從L1,L2,L3L_1,L_2,L_3L1?,L2?,L3?中找到一個點,使得這個點到A,B,CA,B,CA,B,C的路徑不相交,那么我們要求的就是從這個點到BBB的距離,這個就不用證明了吧QwQ…
然后問題就轉換成了裸的LCA
Code:
#include<iostream> #include<cstdio> #define size 200010using namespace std;int n,q,num; int tot,ver[size*2],Next[size*2],head[size*2]; int fa[size][22],d[size];void add(int x,int y) {ver[++tot]=y;Next[tot]=head[x];head[x]=tot; }void dfs(int f,int fath) {d[f]=d[fath]+1;fa[f][0]=fath;for(int i=1;i<=20;i++)fa[f][i]=fa[fa[f][i-1]][i-1];for(int i=head[f];i;i=Next[i]){int y=ver[i];if(y!=fath) dfs(y,f);} }int lca(int x,int y) {if(d[x]<d[y]) swap(x,y);for(int i=20;i>=0;i--)if(d[fa[x][i]]>=d[y]) x=fa[x][i];if(x==y) return x;for(int i=20;i>=0;i--){if(fa[x][i]!=fa[y][i]){x=fa[x][i];y=fa[y][i];}}return fa[x][0]; }int dist(int x,int y) {int mid=lca(x,y);return d[x]+d[y]-2*d[mid]; }int main() {scanf("%d%d%d",&n,&q,&num);for(int i=1;i<=n-1;i++){int x,y;scanf("%d%d",&x,&y);add(x,y);add(y,x);}dfs(1,0);for(int i=1;i<=q;i++){int a,b,c;scanf("%d%d%d",&a,&b,&c);int qwq_1=lca(a,b);int qwq_2=lca(b,c);int qwq_3=lca(a,c);if(d[qwq_2]>d[qwq_1]) qwq_1=qwq_2;if(d[qwq_3]>d[qwq_1]) qwq_1=qwq_3;printf("%d\n",1+dist(qwq_1,b));}return 0; }總結
以上是生活随笔為你收集整理的泉州集训之HSY的day1的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Laravel系列6.4】管道过滤器
- 下一篇: html5绘制好看的时钟,利用纯html