烂
原题连接
A 模拟
搬砖题
每条边两种情况 要么都相等,要么小的两条相加等于大的
(一开始没有注意到三个矩形的大小关系 卡了很长时间...
B 找规律
- 在这三个矩形线上的球不会进袋,会一直转
只有在对角线上的球能进 - 球之间会发生碰撞
但是同一轨迹的相撞不变轨迹
垂直轨迹的相撞极限一换一,也相当于轨迹不变
cpp
void solve(){
int n,s;cin>>n>>s;
int ans=0;
forr(i,1,n){
int dx,dy,x,y;
cin>>dx>>dy>>x>>y;
if(x+y==s&&dx*dy<0)ans++;
else if(x==y&&dx*dy>0)ans++;
}
cout<<ans<<endl;
}
C 思维
读假题了 以为不会算根的d(v)值...
- 先判定合法 树的两种极端结构------
- 链(除了根,其他d(v)=1, s u m m i n = i + n − 1 sum_{min}=i+n-1 summin=i+n−1)
- 菊花图(d(v)=min(root,v), s u m m a x = i ( i + 1 ) 2 + i ( n − i ) sum_{max}=\frac{i(i+1)}{2}+i(n-i) summax=2i(i+1)+i(n−i)
- 之后问题在于怎么分m
cpp
void solve(){
int n,m;cin>>n>>m;
vector<int>a(n+1,0);
if(!(m>=n&&m<=n*(n+1)/2))return cout<<"-1\n",void();
int id=0,dt=m;
//分配m
forr(i,1,n){
if(dt>n-i+1)dt-=(n-i+1),a[++id]=i;//后面数都能分到i
else{//不够分 剩了dt个1分给n-dt+1~n i~n-dt不分
forr(j,i,n-dt)a[++id]=i-1;//能分到上一个 i-1
forr(j,n-dt+1,n)a[++id]=i;
break;
}
}
//a[]数组非递减
//d(root)=root,最大的是根,没有其他小的数覆盖
int pre=a[n],nxt=a[n]+1;//nxt是被root覆盖的点
cout<<a[n]<<endl;
reforr(i,1,n-1){
if(a[i]==a[i+1])cout<<pre<<' '<<(pre=nxt++)<<endl;//如果相等 说明有大的数被覆盖了 小的连接大的
else cout<<pre<<' '<<(pre=a[i])<<endl;//不相等 连续的 没有大的数被覆盖
}
}
从菊花图 s u m m a x sum_{max} summax开始向m凑
大的点合并到小的点可以让sum变小
cpp
void solve()
{
int n,m;cin>>n>>m;
int rt=-1;
forr(i,1,n){
int low=i+n-1,up=i*(i+1)/2+(n-i)*i;
if(low<=m&&m<=up){
rt=i;
break;
}
}
if(rt==-1)return cout<<-1<<endl,void();
int dis=rt*(rt+1)/2+(n-rt)*rt-m;
vector<int>fa(n+1,rt);//菊花图
reforr(i,1,n){
if(dis==0)break;
int d=min(i,rt);//当前的d(v)
//d(v)-1是减掉最大的
if(dis>=d-1){//移到1下面
dis-=(d-1);
fa[i]=1;
}else{//dis<d-1
int aim=d-dis;
fa[i]=aim;
break;
}
}
cout<<rt<<endl;
forr(i,1,n){
if(i!=rt)cout<<fa[i]<<' '<<i<<endl;
}
}
D 组合数学 鸽巢原理
题意:对任意 n ∗ m n*m n∗m,每个数[1,k]的矩阵,能找到 a ∗ b a*b a∗b相同的数组成的子矩阵,找字典序最小的(n,m)
首先让n最小,重复k个数比重复k个数的组合的种数要少
所以先考虑对单列, k + 1 k+1 k+1行会重复一个数,需要a行重复的, n = ( a − 1 ) k + 1 n=(a-1)k+1 n=(a−1)k+1
对每行,设每列有x种组合 m = ( b − 1 ) x + 1 m=(b-1)x+1 m=(b−1)x+1
这x种要满足之前每列有a个重复的, x m a x = k ⋅ C n a x_{max}=k\cdot C_n^a xmax=k⋅Cna,就是n个数中选a个相同,相同的数有k种情况
cpp
int qpow(int x,int a){
int res=1;
while (a)
{
if(a&1)res=res*x%mod;
x=x*x%mod;
a>>=1;
}
return res%mod;
}
int inv(int x){
return qpow(x,mod-2)%mod;
}
int C(int n,int a){
int res=1,tp=1;
forr(i,1,a){
tp=tp*i%mod;
}
forr(i,n-a+1,n){
res=res*i%mod;
}
return res*inv(tp)%mod;
}
void solve(){
int a,b,k;cin>>a>>b>>k;
int n=((a-1)*k+1)%mod;
int m=(k*C(n,a)%mod*(b-1)%mod+1)%mod;
cout<<n<<' '<<m<<endl;
}