2018.10.24 練習賽
阿新 • • 發佈:2018-10-25
ref ron 每次 using span detail 復雜 找到 long
T1 【NOIP2017模擬】Fibonacci
題解:
本以為這道題是一個類似的之前做的一道斐波那契的\(DP\),一看數據範圍就知道應該是亂搞差不離了\(,,,\)
我們預處理前\(45\)項\(Fibonacci\)數列,發現已經突破\(1e9\)了,於是我們直接每次詢問掃一遍即可,時間復雜度\(O(T*45*45)\)
\(code\):
#include<cstdio> #include<iostream> #include<algorithm> #include<ctype.h> #include<vector> #include<queue> #include<cstring> #include<map> #include<cmath> #include<stdlib.h> #include<ctime> #define lowbit(x) (x&-x) #define ll long long #define ld double #define mod 998244353 using namespace std; char buf[1<<20],*p1,*p2; inline char gc() { // return getchar(); return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin))==p1?0:*p1++; } template<typename T> inline void read(T &x) { char tt; bool flag=0; while(!isdigit(tt=gc())&&tt!='-'); tt=='-'?(flag=1,x=0):(x=tt-'0'); while(isdigit(tt=gc())) x=x*10+tt-'0'; if(flag) x=-x; } ll f[50],t,n; int main() { read(t); f[1]=f[2]=1; for(int i=3;i<=46;i++) f[i]=f[i-1]+f[i-2]; while(t--) { bool flag=0; read(n); for(int i=0;i<=46;i++) { if(!flag) for(int j=0;j<=46;j++) { if(f[i]*f[j]>n) break; if(f[i]*f[j]==n) {flag=1;break;} } } if(flag) puts("Yes"); else puts("No"); } }
T2【NOIP2017模擬】一樣遠
題解:
很顯然,當兩點之間的點數為奇數時,此時有解,否則顯然無解,而有解時,顯然我們應該去找中點;
我們對有解的情況分情況討論:
\(1.dep[x]==dep[y]:\)
這時候只用將x、y上提到中點的前一個點就好,\(N-Sz[xx]-Sz[yy]\)即可;
\(2.dep[x]!=dep[y]:\)
我們假設\(dep[x]>dep[y]\),那麽我們先找到他們的中點,再用中點的子樹大小減去包含了\(x\)的子樹的大小就行了;
\(code:\)
#include<cstdio> #include<iostream> #include<algorithm> #include<ctype.h> #include<vector> #include<queue> #include<cstring> #include<map> #include<cmath> #include<stdlib.h> #include<ctime> #define lowbit(x) (x&-x) #define ll long long #define ld double #define mod 998244353 using namespace std; char buf[1<<20],*p1,*p2; inline char gc() { // return getchar(); return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin))==p1?0:*p1++; } template<typename T> inline void read(T &x) { char tt; bool flag=0; while(!isdigit(tt=gc())&&tt!='-'); tt=='-'?(flag=1,x=0):(x=tt-'0'); while(isdigit(tt=gc())) x=x*10+tt-'0'; if(flag) x=-x; } const int maxn=100002; int ans,n,log_[maxn],m; int fa[maxn][20],dep[maxn],sz[maxn]; vector<int>G[maxn]; void dfs(int x,int pre) { fa[x][0]=pre;sz[x]++; for(int i=1;i<=log_[n];i++) if(fa[x][i-1]) fa[x][i]=fa[fa[x][i-1]][i-1]; else break; for(int i=G[x].size()-1;i>=0;i--) { int p=G[x][i]; if(p==pre) continue; dep[p]=dep[x]+1; dfs(p,x);sz[x]+=sz[p]; } } int getlca(int x,int y) { if(x==y) return x; if(dep[x]<dep[y]) swap(x,y); int del=dep[x]-dep[y]; for(int i=log_[n];i>=0;i--) if(del>>i&1) x=fa[x][i]; if(x==y) return x; for(int i=log_[n];i>=0;i--) if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i]; return fa[x][0]; } int moveup(int x,int k) { for(int i=log_[n];i>=0;i--) if(k>>i&1) x=fa[x][i]; return x; } int main() { read(n);log_[0]=-1; for(int i=1;i<=n;i++) log_[i]=log_[i>>1]+1; for(int i=1;i<n;i++) { int x,y; read(x),read(y); G[x].push_back(y); G[y].push_back(x); } dfs(1,0); read(m); while(m--) { int x,y; read(x),read(y); if(x==y) {printf("%d\n",n);continue;} int len=dep[x]+dep[y]-(dep[getlca(x,y)]<<1); if(len&1) {puts("0");continue;} if(dep[x]==dep[y]) { int k=(len>>1)-1; int xx=moveup(x,k); int yy=moveup(y,k); printf("%d\n",n-sz[xx]-sz[yy]); } if(dep[x]!=dep[y]) { int k=(len>>1)-1; if(dep[x]<dep[y]) swap(x,y); int xx=moveup(x,k); printf("%d\n",sz[fa[xx][0]]-sz[xx]); } } }
T3 【NOIP2017模擬】拆網線
題解:
貪心,顯然兩兩相連接是最優的情況,如果不能滿足就往裏面加點,每加一次答案就多一條邊;
\(code:\)
#include<cstdio> #include<iostream> #include<algorithm> #include<ctype.h> #include<vector> #include<queue> #include<cstring> #include<map> #include<cmath> #include<stdlib.h> #include<ctime> #define lowbit(x) (x&-x) #define ll long long #define ld double #define mod 998244353 using namespace std; char buf[1<<20],*p1,*p2; inline char gc() { // return getchar(); return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin))==p1?0:*p1++; } template<typename T> inline void read(T &x) { char tt; bool flag=0; while(!isdigit(tt=gc())&&tt!='-'); tt=='-'?(flag=1,x=0):(x=tt-'0'); while(isdigit(tt=gc())) x=x*10+tt-'0'; if(flag) x=-x; } const int maxn=100002; int t,n,k,ans; bool book[maxn]; vector<int>G[maxn]; void dfs(int x,int pre) { for(int i=G[x].size()-1;i>=0;i--) { int p=G[x][i]; if(p==pre) continue; dfs(p,x);if(!book[p]&&!book[x]) ans++,book[x]=1; } } int main() { read(t); while(t--) { read(n),read(k);ans=0; for(int i=1;i<=n;i++) G[i].clear(),book[i]=0; for(int i=1;i<n;i++) { int x; read(x); G[x].push_back(i+1); G[i+1].push_back(x); // int y; // read(x),read(y); // G[x].push_back(y); // G[y].push_back(x); } dfs(1,0); if((ans<<1)>=k) printf("%d\n",(k>>1)+(k&1)); else printf("%d\n",k-ans); } }
2018.10.24 練習賽