Centos7 部署GlusterFS
T1001Road To The 3rd Building
總的方案數有 n(n+2)/2 種。然後考慮每種方案的貢獻:
設s[i]為字首和,Ans是總的貢獻,ans[i]是中間過程的累加和。
ans[i] = s[n-i+1] - s[i-1] + ans[i-1]
Ans= $\sum_{i=1}^n$ ans[i]/i
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int mod= 1e9+7; 5 const int N=2e5+10; 6 ll s[N];7 ll ans[N]; 8 ll quick_pow(ll x,ll y){ 9 ll res=1; 10 while(y){ 11 if(y&1) res=res*x%mod; 12 x=x*x%mod; 13 y>>=1; 14 } 15 return res; 16 } 17 int main() 18 { 19 int T; 20 scanf("%d",&T); 21 while(T--){ 22 ll Ans=0; 23 ll n;24 scanf("%lld",&n); 25 for(int i=1;i<=n;i++){ 26 scanf("%lld",&s[i]); 27 s[i]=(s[i]+s[i-1])%mod; 28 } 29 for(int i=1;i<=n;i++){ 30 ans[i]=(s[n-i+1]-s[i-1]+ans[i-1]+mod)%mod; 31 ll inv=quick_pow(i,mod-2); 32Ans=(Ans+ans[i]*inv%mod)%mod; 33 } 34 ll inv=quick_pow(n*(n+1)%mod,mod-2); 35 Ans=(Ans*2%mod*inv)%mod; 36 printf("%lld\n",Ans); 37 } 38 return 0; 39 }
T1002Little Rabbit's Equation
先找出方程最小可能是幾進位制(通過方程中的數字、字母判斷),然後從 最小可能的進位制 到16進位制迴圈模擬,找到符合方程的最小進位制。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 char s[30]; 5 int main() 6 { 7 while(~scanf("%s",s+1)){ 8 int len=strlen(s+1); 9 int mx=2; 10 for(int i=1;i<=len;i++){ 11 if(s[i]>='0'&&s[i]<='9') 12 mx=max(mx,s[i]-48+1); 13 if(s[i]>='A'&&s[i]<='F') 14 mx=max(mx,s[i]-'A'+10+1); 15 } 16 bool flag=0; 17 for(ll k=mx;k<=16;k++){ 18 ll x=0,y=0,z=0; 19 int i=1,j; 20 while(s[i]!='+'&&s[i]!='-'&&s[i]!='*'&&s[i]!='/'){ 21 if(s[i]>='A'){ 22 x=x*k+s[i]-'A'+10; 23 } 24 else x=x*k+s[i]-48; 25 i++; 26 } 27 if(s[i]=='+') j=1; 28 else if(s[i]=='-') j=2; 29 else if(s[i]=='*') j=3; 30 else j=4; 31 i++; 32 while(s[i]!='='){ 33 if(s[i]>='A'){ 34 y=y*k+s[i]-'A'+10; 35 } 36 else y=y*k+s[i]-48; 37 i++; 38 } 39 i++; 40 while(i<=len){ 41 if(s[i]>='A'){ 42 z=z*k+s[i]-'A'+10; 43 } 44 else z=z*k+s[i]-48; 45 i++; 46 } 47 //printf("%lld %lld %lld\n",x,y,z); 48 if(j==1&&x+y==z){ 49 flag=1; 50 printf("%lld\n",k); 51 break; 52 } 53 if(j==2&&x-y==z){ 54 flag=1; 55 printf("%lld\n",k); 56 break; 57 } 58 if(j==3&&x*y==z){ 59 flag=1; 60 printf("%lld\n",k); 61 break; 62 } 63 if(j==4&&x==y*z){ 64 flag=1; 65 printf("%lld\n",k); 66 break; 67 } 68 } 69 if(flag==0) printf("-1\n"); 70 } 71 return 0; 72 }
T1005Fragrant numbers
區間dp,通過觀察,只需要前13個數便可代表所有的數來構造前5000個數(當然,數不一定全部構造出來)。
dp[ i ][ j ][ k ] 表示 i - j 區間能否構造出k。
對於每個詢問,只需要找到dp[ 1 ][ i ][ n ] = 1 的最小的右端點 i 。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N=5010; 5 const int a[13]={1,1,4,5,1,4,1,9,1,9,1,1,4}; 6 bool dp[20][20][N]; 7 int ans[N]; 8 int getnum(int l,int r){ 9 int num=0; 10 for(int i=l;i<=r;i++) 11 num=num*10+a[i-1]; 12 return num; 13 } 14 void Prepare(){ 15 for(int i=1;i<=13;i++){ 16 dp[i][i][a[i-1]]=1; 17 } 18 for(int len=1;len<13;len++){ 19 for(int i=1;i+len<=13;i++){ 20 int j=i+len; 21 if(len<4){ 22 int x=getnum(i,j); 23 if(x<=5000) dp[i][j][x]=1; 24 } 25 for(int k=i;k<j;k++){ 26 for(int u=1;u<=5000;u++){ 27 if(dp[i][k][u]==0) continue; 28 for(int v=1;v<=5000;v++){ 29 if(dp[k+1][j][v]==0) continue; 30 if(u+v<=5000) dp[i][j][u+v]=1; 31 if(u*v<=5000) dp[i][j][u*v]=1; 32 if(u+v>5000&&u*v>5000) break; 33 } 34 } 35 } 36 } 37 } 38 memset(ans,-1,sizeof(ans)); 39 for(int i=13;i>=1;i--) 40 for(int j=1;j<=5000;j++) 41 if(dp[1][i][j]) 42 ans[j]=i; 43 } 44 int main() 45 { 46 Prepare(); 47 int T; 48 scanf("%d",&T); 49 while(T--){ 50 int n; 51 scanf("%d",&n); 52 printf("%d\n",ans[n]); 53 } 54 return 0; 55 }
T1006A Very Easy Graph Problem
有一個明顯的結論 $\sum_{i=1}^n$ $2^i$ < $2^{n+1}$
所以可以從第一條邊開始建立最小生成樹,因為根據以上結論,每兩個點之間的最短路經過的邊一定在最小生成樹上。
這樣可以統計最小生成樹上每條邊的貢獻(經過的次數*邊長)。我的方法是直接兩次dfs,第一次統計子樹中0和1的個數,第二次計算貢獻。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int mod=1e9+7; 5 const int N=1e5+10; 6 const int M=2e5+10; 7 int head[N],to[M],nxt[M]; 8 ll w[M]; 9 int tot; 10 int n,m; 11 int a[N]; 12 int s[N]; 13 ll num0[N],num1[N]; 14 ll ans; 15 void init(){ 16 tot=0; 17 ans=0; 18 memset(head,0,sizeof(head)); 19 } 20 int find_set(int x){ 21 if(x!=s[x]) return s[x]=find_set(s[x]); 22 return s[x]; 23 } 24 inline void add(int u,int v,ll x){ 25 to[++tot]=v,nxt[tot]=head[u],w[tot]=x,head[u]=tot; 26 } 27 void dfs(int u,int fa){ 28 if(a[u]==0) num0[u]=1,num1[u]=0; 29 else num1[u]=1,num0[u]=0; 30 for(int i=head[u];i;i=nxt[i]){ 31 int v=to[i]; 32 if(v==fa) continue; 33 dfs(v,u); 34 num0[u]+=num0[v]; 35 num1[u]+=num1[v]; 36 } 37 } 38 void dfs2(int u,int fa){ 39 for(int i=head[u];i;i=nxt[i]){ 40 int v=to[i]; 41 if(v==fa) continue; 42 ans=(ans+(num0[v]*(num1[1]-num1[v]+mod)%mod+num1[v]*(num0[1]-num0[v]+mod)%mod)*w[i]%mod)%mod; 43 dfs2(v,u); 44 } 45 } 46 int main() 47 { 48 int T; 49 scanf("%d",&T); 50 while(T--){ 51 init(); 52 scanf("%d%d",&n,&m); 53 for(int i=1;i<=n;i++){ 54 scanf("%d",&a[i]); 55 s[i]=i; 56 } 57 ll val=1; 58 for(int i=1;i<=m;i++){ 59 int u,v; 60 scanf("%d%d",&u,&v); 61 val=val*2%mod; 62 int x=find_set(u),y=find_set(v); 63 if(x!=y){ 64 s[y]=x; 65 add(u,v,val); 66 add(v,u,val); 67 } 68 } 69 dfs(1,0); 70 dfs2(1,0); 71 printf("%lld\n",ans); 72 } 73 return 0; 74 }
T1009Divisibility
在b進位制下,一個數被x整除的充要條件是所有位上的數加起來可以被x整除,則(b-1)是x的倍數。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int mod= 998244353; 5 6 int main() 7 { 8 int T; 9 scanf("%d",&T); 10 while(T--){ 11 ll b,x; 12 scanf("%lld%lld",&b,&x); 13 if((b-1)%x==0){ 14 printf("T\n"); 15 } 16 else printf("F\n"); 17 } 18 return 0; 19 }
T1010Expectation
先用矩陣樹定理求出所有生成樹的個數。
然後進行二進位制拆位。即對於邊權的每一位,找出邊權的那一位為1的所有邊,再次用矩陣樹定理求出該位為1的所有邊的生成樹的個數,乘上該位的值,從而算出每一位的貢獻。
把每一位的貢獻加起來除以生成樹的總個數,便是期望。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 const int N=110; 5 const int M=1e4+10; 6 const int mod=998244353; 7 struct edge{ 8 int from,to; 9 ll d; 10 }e[M]; 11 ll a[N][N]; 12 ll ans; 13 int n,m; 14 ll quick_pow(ll x,ll y){ 15 ll res=1; 16 while(y){ 17 if(y&1) res=res*x%mod; 18 x=x*x%mod; 19 y>>=1; 20 } 21 return res; 22 } 23 void work(){ 24 for(int i=2;i<=n;i++){ 25 if(!a[i][i]) 26 for(int j=i+1;j<=n;j++){ 27 if(a[j][i]){ 28 ans=-ans; 29 swap(a[i],a[j]); 30 break; 31 } 32 } 33 ll inv=quick_pow(a[i][i],mod-2); 34 for(int j=i+1;j<=n;j++){ 35 ll tmp=a[j][i]*inv%mod; 36 for(int k=i;k<=n;k++){ 37 a[j][k]=(a[j][k]-a[i][k]*tmp%mod+mod)%mod; 38 } 39 } 40 } 41 } 42 void solve(ll lim){ 43 ans=1; 44 for(int i=1;i<=n;i++) 45 for(int j=1;j<=n;j++) 46 a[i][j]=0; 47 for(int i=1;i<=m;i++){ 48 int u=e[i].from,v=e[i].to; 49 ll w=e[i].d; 50 if(!(w&lim)) continue; 51 a[u][u]++; 52 a[v][v]++; 53 a[u][v]--; 54 a[v][u]--; 55 } 56 work(); 57 for(int i=2;i<=n;i++) 58 ans=(ans*a[i][i])%mod; 59 ans=(ans%mod+mod)%mod; 60 } 61 int main() 62 { 63 int T; 64 scanf("%d",&T); 65 while(T--){ 66 scanf("%d%d",&n,&m); 67 for(int i=1;i<=m;i++){ 68 scanf("%d%d%lld",&e[i].from,&e[i].to,&e[i].d); 69 } 70 ll x=0; 71 for(int i=0;i<30;i++){ 72 ll lim=(1<<i); 73 solve(lim); 74 x=(x+lim*ans%mod)%mod; 75 } 76 solve((1<<30)-1); 77 ll sum=ans; 78 ll inv=quick_pow(sum,mod-2); 79 printf("%lld\n",x*inv%mod); 80 } 81 return 0; 82 }