牛客小白月賽8
阿新 • • 發佈:2018-11-10
A-病毒感染
題意給一顆樹,然後要求這個樹上到所有點權值最小的那個點。實際上這個點就是樹的重心,直接去求樹的重心就可以了。
#include<bits/stdc++.h> using namespace std; const int maxn=1e5+50; struct node { int v,next; }e[maxn]; int cnt=0,front[maxn],d[maxn],f[maxn],mmin=0x3f3f3f3f; int n,m; inline void addedge(int u,int v) { e[++cnt].v=v; e[cnt].next=front[u]; front[u]=cnt; } void dfs(int u,int fa) { d[u]=1,f[u]=0; for(int i=front[u];i;i=e[i].next) { int v=e[i].v; if(v==fa) continue; dfs(v,u); d[u]+=d[v]; f[u]=max(f[u],d[v]); } f[u]=max(f[u],n-d[u]); mmin=min(mmin,f[u]); } int main() { int u,v; scanf("%d%d",&n,&m); for(int i=1;i<=m;++i) { scanf("%d%d",&u,&v); addedge(u,v); addedge(v,u); } dfs(1,0); for(int i=1;i<=n;++i) if(f[i]==mmin) printf("%d ",i); }
B-切題之路
這個只要理解題目然後模擬即可
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll maxn=1e5+50; struct node { ll tim,le; }p[maxn]; int main() { ll n,t,a,b,rqy=0,clccle=0; scanf("%lld%lld%lld%lld",&n,&t,&a,&b); ll rqyt=t;ll clcclet=t; for(ll i=1;i<=n;++i) scanf("%lld",&p[i].tim); for(ll i=1;i<=n;++i) scanf("%lld",&p[i].le); for(ll i=1;i<=n;++i) { if(p[i].le<a&&clcclet>=p[i].tim) clccle++,clcclet-=p[i].tim; if(p[i].le>=b&&rqyt>=p[i].tim*2) rqy++,rqyt-=2*p[i].tim; if(p[i].le<b&&rqyt>=p[i].tim) rqy++,rqyt-=p[i].tim; } printf("%lld %lld\n",clccle,rqy); return 0; }
C-神祕鑰匙
直接考慮求 求出答案即可
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
ll fastpow(ll x , ll y)
{
ll ans=1;
while(y)
{
if(y&1) (ans*=x)%=mod;
(x*=x)%=mod;
y/=2;
}
return ans%mod;
}
int main()
{
ll n;
scanf("%lld",&n);
printf("%lld",(n%mod*fastpow(2,n-1))%mod);
}
D-迷之盒子
首先我們先考慮如果沒有條件約束的情形,所有得情形應當為 ,然後我們找出這裡面所有不符合得情形的數目,我們考慮吧剩下的先劃分成不合法的個數是 答案就是兩者相減即可,由於資料量比較大要用到Lucas定理來求解
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const ll mod=1e9+7;
ll fpow(ll x,ll y)
{
ll ans=1;
while(y) {
if(y&1) (ans*=x)%=mod;
(x*=x)%=mod;
y/=2;
}
return ans%mod;
}
ll cal(ll n,ll m) {
ll ans=1;
for(int i=1;i<=m;++i){
ll t1=(n-m+i)%mod;
ll t2=i%mod;
ans=ans*(t1*fpow(t2,mod-2)%mod)%mod;
}
return ans%mod;
}
ll lucas(ll n,ll m) {
if(m==0) return 1;
return cal(n%mod,m%mod) *lucas(n/mod,m/mod) %mod;
}
int main()
{
ll n,m,k,ans=0;
scanf("%lld%lld%lld",&n,&m,&k);
ll sum=lucas(n+m-1,n-1);
ll upper=m/(k+1);
for(ll i=1;i<=upper;++i)
(ans+=lucas(n,i)*lucas(m+n-i*(k+1)-1,n-1)%mod)%=mod;
printf("%lld\n",sum-ans);
return 0;
}
E-詭異數字
注意到是對一個區間裡面判斷數字性質的問題,很容易聯想到數位dp.我們一個四維引數dfs,分別儲存當前的數位,前面的數位是否被限定,前驅,以及前驅重複的個數.然後就可以開始胡亂轉移了
#include<bits/stdc++.h>
#define int long long
using namespace std;
typedef long long ll;
const int maxn=20;
const int mod=20020219;
int limit[maxn],len[maxn],f[maxn][11];
ll dfs(int pos,bool islimit,int pre,int sum)
{
if(sum>limit[pre]) return 0;
if(pos==0) return 1;
if(!islimit&&f[pos][pre]!=-1) return f[pos][pre];
int up=islimit?len[pos]:9;
int temp=0;
for(int i=0;i<=up;i++)
temp+=dfs(pos-1,islimit&&i==len[pos],i,i==pre?sum+1:1);
return islimit?temp:f[pos][pre]=temp;
}
ll solve(ll sum)
{
if(sum==-1) return 0;
int cnt=0;
while(sum){
len[++cnt]=sum%10;
sum/=10;
}
ll ans=0;
for(int i=0;i<=len[cnt];++i)
(ans+=dfs(cnt-1,i==len[cnt],i,1))%=mod;
return ans%mod;
}
signed main()
{
int line;
scanf("%lld",&line);
for(int i=1;i<=line;i++)
{
memset(f,-1,sizeof(f));
memset(limit,0x3f3f3f,sizeof(limit));
ll l,r;int n;
scanf("%lld%lld%lld",&l,&r,&n);
for(int t=1;t<=n;++t){
int x,len;
scanf("%lld%lld",&x,&len);
limit[x]=min(limit[x],len);
}
printf("%lld\n",(solve(r)-solve(l-1)+mod)%mod);
}
}
F-數列操作
裸的平衡樹
#include<cstdio>
#include<algorithm>
#define FOR(i,s,t) for(register int i=s;i<=t;++i)
#define ls k<<1,l,mid
#define rs k<<1|1,mid+1,r
#define gc getchar()
using namespace std;
const int N=400011;
int n,p;
int a[N],b[N],c[N];
namespace Segment_Tree{
int tr[N];
inline void modify(int x,int v,int k=1,int l=1,int r=c[0]){
tr[k]+=v;
if(l==r)return ;
int mid=(l+r)>>1;
x<=mid?modify(x,v,ls):modify(x,v,rs);
}
inline int query_num(int x,int k=1,int l=1,int r=c[0]){
if(l==r)return l;
int mid=(l+r)>>1;
return x<=tr[k<<1]?query_num(x,ls):query_num(x-tr[k<<1],rs);
}
inline int query_pos(int x,int type,int k=1,int l=1,int r=c[0]){
if(l==r){
if(type==3)return 1;
if(type==5)return 0;
if(type==6)return tr[k]+1;
}
int mid=(l+r)>>1;
return x<=mid?query_pos(x,type,ls):(tr[k<<1]+query_pos(x,type,rs));
}
}
using namespace Segment_Tree;
inline void disc_init(){
sort(c+1,c+c[0]+1);
c[0]=unique(c+1,c+c[0]+1)-c-1;
FOR(i,1,n)
if(a[i]!=4)b[i]=lower_bound(c+1,c+c[0]+1,b[i])-c;
}
inline int read(){
char c;while(c=gc,c==' '||c=='\n');int data=0,f=1;
c=='-'?f=-1:data=c-48;
while(c=gc,c>='0'&&c<='9')data=(data<<1)+(data<<3)+c-48;
return data*f;
}
int main(){
n=read();
FOR(i,1,n){
a[i]=read();b[i]=read();
if(a[i]!=4)c[++c[0]]=b[i];
}
disc_init();
FOR(i,1,n){
if(a[i]==1)modify(b[i],1);
if(a[i]==2)modify(b[i],-1);
if(a[i]==3)printf("%d\n",query_pos(b[i],3));
if(a[i]==4)printf("%d\n",c[query_num(b[i])]);
if(a[i]==5)printf("%d\n",c[query_num(query_pos(b[i],5))]);
if(a[i]==6)printf("%d\n",c[query_num(query_pos(b[i],6))]);
}
return 0;
}
紅包期望
簡單的概率論問題,根據全期望公式知道前面m個人先後取值是無所謂的都是都是 ,而後面m個人的期望全部是0.
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double ld;
typedef pair<int,int> pii;
typedef vector<int> vi;
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define ini(a,x) memset(a,x,sizeof(a))
const int inf=0x3f3f3f3f;
const int mod=1e9+7;
const ld pi=acos(-1);
const ld eps=1e-9;
void read(int &x)
{
x=0; int 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(); }
x=x*f;
}
int main()
{
ll m,n,T;
scanf("%lld%lld%lld",&m,&n,&T);
while(T--)
{
ll t;
scanf("%lld",&t);
if(t<=m) printf("%lld\n",n/m);
else printf("0\n");
}
return 0;
}
H-機房網路
據說是網路流+線段樹維護,目前還是知識盲區
I-路燈孤影
似乎是一個很難的dp,雖然隊友一度堅持可以暴力剪枝來做qwq
J-好的序列
Rqy的毒瘤題,不知道誰會,反正我不會