標籤:題目 puts \n 除了 tor i++ back for 相交
Wannafly挑戰賽25遊記A - 因子題目大意:
令\(x=n!(n\le10^{12})\),給定一大於\(1\)的正整數\(p(p\le10000)\)求一個\(k\)使得\(p^k|x\)並且\(p^{k+1}\not|x\)的因子。
思路:
枚舉\(p\)的每一個質因數\(q\),求出它在\(n!\)出現次數\(/p\)中出現次數,取\(\min\)即可。對於一個質因數\(q\),在\(n!\)中出現的次數等於\(\sum_{i=1}^{\inf}\frac n{q^i}\)。
原始碼:
#include<cstdio>#include<cctype>#include<climits>#include<algorithm>typedef long long int64;inline int64 getint() { register char ch; while(!isdigit(ch=getchar())); register int64 x=ch^'0'; while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); return x;}int main() { int64 m=getint(),p=getint(),k=LLONG_MAX; for(register int64 i=2;i<=p;i++) { if(p%i==0) { int64 tmp=0,n=m,cnt=0; while(n) { tmp+=n/i; n/=i; } while(p%i==0) { p/=i; cnt++; } k=std::min(k,tmp/cnt); } } printf("%lld\n",k); return 0;}
B - 面積並題目大意:
有一個正\(n\)邊形,它的外接圓的圓心位於原點,半徑為\(l\)。以原點為圓心,\(r\)為半徑作一個圓,求圓和這個正\(n\)邊形的面積並。
思路:
割補法直接算即可。注意精度問題。
原始碼:
#include<cmath>#include<cstdio>#include<cctype>typedef long long int64;inline int64 getint() { register char ch; while(!isdigit(ch=getchar())); register int64 x=ch^'0'; while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); return x;}long double n,l,r,y;int main() { n=getint(),l=getint(),r=getint(); y=l*cosl(M_PIl/n); if(r>l) { printf("%.2Lf\n",M_PIl*r*r); return 0; } if(r<y) { printf("%.2Lf\n",.5*l*l*n*sinl(M_PIl*2/n)); return 0; } printf("%.2Lf\n",r*r*acosl(y/r)*n+y*(sqrtl(l*l-y*y)-sqrtl(r*r-y*y))*n); return 0;}
C - 期望運算元題目大意:
\(T(T\le10^6)\)組詢問\(x,q(x,q\le10^7)\),每次操作將\(x\)變成\([x,q]\)中的一個隨機整數,求\(x\)變到\(q\)期望需要多少次操作。
思路:
顯然\(x\to q\)相當於\(0\to x-q\)。
如果從\(0\)開始操作,\(f_i\)表示變成\(i\)的期望次數,那麼\(f_i=\frac{\sum_{j=0}^if_i}{i+1}+1\)。
變形得:\(f_i=\frac{1+\sum_{j=0}^{i-1}f_i}{i}+1\)。
首碼和最佳化預先處理\(f\)即可。
原始碼:
#include<cstdio>#include<cctype>inline int getint() { register char ch; while(!isdigit(ch=getchar())); register int x=ch^'0'; while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); return x;}typedef long long int64;const int N=1e7+1,mod=998244353;int f[N],g[N],inv[N];int main() { inv[1]=1; for(register int i=2;i<N;i++) { inv[i]=(int64)(mod-mod/i)*inv[mod%i]%mod; } for(register int i=1;i<N;i++) { f[i]=(int64)(g[i-1]+i+1)*inv[i]%mod; (g[i]=g[i-1]+f[i])%=mod; } for(register int T=getint();T;T--) { const int x=getint(),q=getint(); printf("%d\n",f[q-x]); } return 0;}
D - 玩遊戲題目大意:
有一張\(n\)個點\(m\)條邊的帶正權的簡單無向圖,其中除了\(1\)號點和\(n\)號點每個點度數小於等於\(2\)。
A和B輪流操作,A先手,每次操作的人可以選擇一條仍然存在的邊,並且使得邊權減\(1\)。如果有一條邊邊權減為了\(0\),它會立即消失。
當\(1\)和\(n\)不連通時,上一個操作的人輸。問A是否有必勝策略。
思路:
首先給出的圖相當於若干條串連\(1\)和\(n\)的不相交的鏈,其餘邊都和\(1\)到\(n\)的連通性無關。
在結束遊戲前的最後一步一定是剩下一條邊權全是\(1\)的鏈。如果剩下的最後一條路徑確定了,遊戲的總步數也確定了,那麼先後手的勝負也確定了。因此我們可以通過鏈上的邊數的奇偶性來判斷這條連是誰的必勝路徑。
那麼雙方的策略就是儘可能切斷使對方必勝的路徑。切斷一條路徑需要的步數是這條路徑上的權值的最小值。我們只需要比較雙方切斷對方必勝的路徑所需要的步數即可。
原始碼:
#include<cstdio>#include<cctype>#include<vector>#include<climits>inline int getint() { register char ch; while(!isdigit(ch=getchar())); register int x=ch^'0'; while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); return x;}typedef long long int64;const int N=1e5+1;int n,m;int64 sum[N],cnt[2];struct Edge { int to,w;};std::vector<Edge> e[N];inline void add_edge(const int &u,const int &v,const int &w) { e[u].push_back((Edge){v,w}); e[v].push_back((Edge){u,w});}void dfs(const int &x,const int &par,const int &dep,const int &min) { if(x==n) { sum[dep]+=min; return; } for(auto &j:e[x]) { const int &y=j.to,&w=j.w; if(y==par) continue; dfs(y,x,dep+1,std::min(min,w)); }}int main() { n=getint(),m=getint(); int64 tot=0; for(register int i=0;i<m;i++) { const int u=getint(),v=getint(),w=getint(); add_edge(u,v,w); tot+=w; } dfs(1,0,0,INT_MAX); for(register int i=1;i<=n;i++) { cnt[i&1]+=sum[i]; } puts(cnt[tot&1]<=cnt[!(tot&1)]?"Yes":"No"); return 0;}
Wannafly挑戰賽25遊記