2019-2020 ACM集訓隊暑假集訓第一次考核
阿新 • • 發佈:2020-08-08
篝火晚會
一棵樹,求一個點,使得所有點到該點的距離和最小,選擇m個點,求期望距離,
把重心挑出來,選擇m個點一共有C(n,m)種情況,每個情況覆蓋m個點,總共有n個點,平攤下來就是 每個點對答案的貢獻 ,C(n,m)*m / n
除n要乘一個逆元。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=1e6+500; const ll mod=1e9+7; struct edge{int v,next;}e[N*5]; int ecnt=0; int head[N]; int n,m;View Codevoid add(int u,int v){ e[ecnt].v=v;e[ecnt].next=head[u];head[u]=ecnt++; } int root,Max; int dep[N]; int size[N],maxv[N]; void init(){ memset(dep,0,sizeof dep); memset(head,-1,sizeof head); ecnt=0; Max=1e9; } void dfs_size(int u,int fa){//求子樹大小 size[u]=1;maxv[u]=0; for(int i=head[u];~i;i=e[i].next){int v=e[i].v; if(v==fa)continue; dfs_size(v,u); size[u]+=size[v]; maxv[u]=max(maxv[u],size[v]); } } void dfs_root(int u,int fa){//求根 maxv[u]=max(maxv[u],n-size[u]); if(maxv[u]<Max){ Max=maxv[u]; root=u; } for(int i=head[u];~i;i=e[i].next){int v=e[i].v; if(v==fa)continue; dfs_root(v,u); } } ll fac[N],inv[N]; ll pow_mod(ll a,ll n) { ll ret =1; while(n) { if(n&1) ret=ret*a%mod; a=a*a%mod; n>>=1; } return ret; } void initc() { fac[0]=1; for(int i=1;i<N;i++) { fac[i]=fac[i-1]*i%mod; } } ll Cc(ll x, ll y) { return fac[x]*pow_mod(fac[y]*fac[x-y]%mod,mod-2)%mod; } void dfs(int u,int fa){ for(int i=head[u];~i;i=e[i].next){ int v=e[i].v; if(v==fa)continue; dep[v]=dep[u]+1; dfs(v,u); } } ll quickPower(ll a, ll b,ll m) { //計算a的b次方 ll ans = 1; ll base = a; while (b) { if (b & 1) { ans *= base; ans %= m; } base *= base; base %= m; b >>= 1; //注意是b>>=1 not b>>1 } return ans; } int main(){ init(); initc(); // cout<<"test "<<Cc(9,3)<<endl; //cout<<Cc(5,2)<<endl; scanf("%d %d",&n,&m); // m=min(m,n-m); for(int i=1;i<n;i++){ int u,v;scanf("%d %d",&u,&v); add(u,v); add(v,u); } dfs_size(1,-1); dfs_root(1,-1); dep[root]=0; dfs(root,-1); ll ans=0; ll xn=quickPower(n,mod-2,mod)%mod; ll val=( (Cc(n,m)*m)%mod*xn)%mod; // cout<<val<<endl;a for(int i=1;i<=n;i++)ans+=(val*dep[i])%mod,ans%=mod; ans%=mod; cout<<ans<<endl; return 0; }
真空中的球形雞
不同電荷相互吸引,或者有一個為0,答案為0。
其他都是d,特判0 0 情況。
#include<bits/stdc++.h> using namespace std; typedef long long ll; int main(){ int t; scanf("%d",&t); while(t--){ int ma,mb,ea,eb,d; scanf("%d %d %d %d %d",&ma,&mb,&ea,&eb,&d); double ans=0; if(ea==0&&eb!=0||ea!=0&&eb==0||ea>0&&eb<0||ea<0&&eb>0){ ans=0; } else ans=d*1.0; printf("%.3lf\n",ans); } return 0; }View Code
B_M的憂慮
設wx為第x天的體重,那麼wx=∑ni=1(ai×wx−i), 其中ai是給定的常數
給出前 n 天 的體重 求 第 x 天的 體重。
構建一個矩陣乘法:
a1 a2 a3 a4 a5 a6 .......an w x-1 w x
1 0 0 0 0 0 0 w x-2 w x-1
0 1 0 0 0 0 0 * w x-3 = w x-2
0 0 1 0 0 0 0 w x- 4 w x-3
0 0 0 1 0 0 0 w x-n-1 w x-4
轉化為矩陣快速冪遞推即可。
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N=2e2+50; const int maxn=2e2+50; const ll mod=193; // int n; // struct Mat{ // ll m[200][200]; // // init(){ // // memset(m,0,sizeof m); // // } // }; // Mat Mul(Mat a,Mat b){ // Mat res; // for(int i=0;i<N;i++){ // for(int j=0;j<N;j++){ // for(int k=0;k<N;k++){ // res.m[i][j]=(res.m[i][j]+(a.m[i][k]*b.m[k][j])%mod )%mod; // } // } // } // return res; // } // Mat qpow(Mat a,ll n){ // Mat res; // for(int i=0;i<N;i++)res.m[i][i]=1; // while(n){ // if(n&1)res=Mul(res,a); // a=Mul(a,a); // n>>=1; // } // return res; // } int n; struct Mat{ ll m[120][120]; Mat() {memset(m, 0, sizeof m);} Mat operator * (const Mat c) const {//矩陣乘法 Mat ret; for (int i = 1; i <=n; i++) { for (int j = 1; j <=n; j++) { for (int k = 1; k <=n; k++) { ret.m[i][j] = (ret.m[i][j] + (m[i][k] * c.m[k][j])%mod) % mod; } } } return ret; } void print() { for (int i = 1; i <=n; i++) { for (int j = 1; j <=n; j++) { printf("%d ",m[i][j]); } puts(""); } } }; Mat quickpower(Mat a, ll b) {//矩陣快速冪 Mat ret; for (int i = 1; i <=n; i++) ret.m[i][i] = 1; while (b) { if (b & 1) ret = ret *a; a = a * a; b >>= 1; } return ret; } ll w[200],a[200]; int main(){ ll x; // cout<<"test "<<endl; cin>>n>>x; // cout<<"test "<<endl; for(int i=n;i>=1;i--){ cin>>w[i]; } for(int i=1;i<=n;i++){ cin>>a[i]; } Mat A,B; for(int i=1;i<=n;i++)A.m[1][i]=a[i]; for(int i=2;i<=n;i++){ for(int j=1;j<=n;j++){ if(j==i-1)A.m[i][j]=1; else A.m[i][j]=0; // cout<<A.m[i][j]<<endl; } } // cout<<"A :"<<endl; // A.print(); for(int i=1;i<=n;i++)B.m[i][1]=w[n+1-i]; // cout<<"B :"<<endl; // B.print(); Mat tmp=quickpower(A,x-n); Mat ans=(tmp*B); // B=Mul(qpow(A,x-n),B); cout<<ans.m[1][1]<<endl; // system("pause"); return 0; }View Code
神槍手JoneySun (Super hard version)
考慮反射其實把網格再擴充出來,問題直接轉化為一條射線穿過多少個網格,直接判斷即可。
#include<bits/stdc++.h> using namespace std; const int N=1e5+500; typedef long long ll; // ll n,m; inline __int128 read(){ __int128 x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9'){ x=x*10+ch-'0'; ch=getchar(); } return x*f; } inline void print(__int128 x){ if(x<0){ putchar('-'); x=-x; } if(x>9) print(x/10); putchar(x%10+'0'); } int main(){ int t;cin>>t; while(t--){ __int128 n=read(),m=read(); __int128 x=read(),y=read(),vx=read(),vy=read(),hp=read(),hu=read(),t=read(),ex,ey; ex=x+t*vx;ey=y+t*vy; __int128 tot=0; if(ey>=0)tot+=ey/n; else tot+=(-ey/n)+1; if(ex>=0)tot+=ex/m; else tot+=(-ex/m)+1; if(hu*tot>=hp)puts("Yes"); else puts("No"); // scanf("%lld %lld %lld %lld %lld %lld %lld",&x,&y,&vx,&vy,&hp,&hu,&t); // ll need=ceil(hp*1.0/hu); } // system("pause"); return 0; } // 3 40282366 9209384634 6337460743 1768211456View Code