某毒瘤的分类讨论数学题
作者:互联网
模拟71 T4
首先这个东西你要看懂题,反正我没看懂。。。
关键是不要被一大堆及其形式化的定义以及一堆希伯来文吓住,挺住否则你就没了
建议集中注意力理解定义,其实也不是很难
几阶子集的意思就是有集合里几个元素
一个集合\(S\)的\(k\)阶价值子集就是一个集合的集合,描述了\(S\)所有大小为\(k\),和可以整除\(sum_S\)的子集
那么它让你干啥呢?给你\(n,m,k\),
从这\(n\)个元素的集合中选出大小为\(m\)的子集,要求每个子集中包含\(k\)个元素且这\(k\)个元素之和能整除本来\(m\)个元素之和的子集数量最大,问有多少个大小为\(m\)的子集选出的数量等于最大值
关键在最后一句,如果理解了那么应该就知道暴力怎么打了
首先枚举这\(m\)个元素,再枚举它所有\(k\)阶子集,算出最大的那个\(f\)值,重新枚举一遍看有多少个值等于\(f\)
然而\(n\)没小的,我们显然要推式子
11,22,33,44
这四种比较类似,答案都是直接\(n\)选\(m\)
由于\(m=k\),此时\(f\)值都等于1,所以任选都是最大值,直接算即可
21,32,43
这三种也比较类似,但是难度都有上升
由于\(f\)值最大是\(\dbinom{m}{k}\),所以可以枚举一些情况看有没有不合法
这里是\(m=2,k=1\)的,舍去一种情况
然后是\(m=3,k=2\),这个舍去两种,比上面多了一个类似容斥的东西
最后一个也是基于如此思想,只是计算部分极其复杂,存在各种加减,最后建议直接看式子
本质上就是把一个数拆成三个不同正整数的方案数,也可以视为和前面的结合
这一部分\(m=3,k=2\),\(m=4,k=3\)需要用数论分块优化枚举,是全局复杂度瓶颈
31,41,42
这三种推导较为花里胡哨,最终靠证明玄学系数找到几个元素之间的关系解决问题
先放神仙思路
设系数,找关系,卡范围,解方程
梦回初中
后面就差不多了,只不过变量更多,式子更难解罢了
被支配的感觉,结论大法好。。。
后面稍微有点不同,因为解的方式不太一样
解出\(s,t\)的关键是利用等式把左右两边化成相同的系数
在知道\(s=2\)之后,代入原式,则有
\[2a_1+2a_3=a_2+a_4 \]结合开始的等式,变形有
\[2a_2=a_3+a_1 \]最终代到\(t\)哪里,推出来
\[a_3+a_4=(a2+a_3)-(a_1+a_4)=a_2+2a_3-a_1=a_2+4a_2--6a_1-a_1=5a_2-7a_3 \]然后就可以套结论了
对于小数据直接搜出答案,放一个程序
signed main()
{
for(int i=4;i<=10;i++)
{
int ans=0,ma=0;
for(int p1=1;p1<=i;p1++)
for(int p2=p1+1;p2<=i;p2++)
for(int p3=p2+1;p3<=i;p3++)
for(int p4=p3+1;p4<=i;p4++)
{
int sum=p1+p2+p3+p4;
int ga=(sum%(p1+p2)==0)+(sum%(p1+p3)==0)+(sum%(p1+p4)==0)+(sum%(p2+p3)==0)+(sum%(p2+p4)==0)+(sum%(p3+p4)==0);
ma=max(ga,ma);
}
for(int p1=1;p1<=i;p1++)
for(int p2=p1+1;p2<=i;p2++)
for(int p3=p2+1;p3<=i;p3++)
for(int p4=p3+1;p4<=i;p4++)
{
int sum=p1+p2+p3+p4;
int ga=(sum%(p1+p2)==0)+(sum%(p1+p3)==0)+(sum%(p1+p4)==0)+(sum%(p2+p3)==0)+(sum%(p2+p4)==0)+(sum%(p3+p4)==0);
if(ga==ma)ans++;
}
cout<<ma<<" "<<ans<<endl;
}
}
最后放一个最终答案
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int mod=1e9+7;
const int inv2=5e8+4;
const int inv6=166666668;
const int inv24=41666667;
int n,m,k;
inline int get1(int l,int r){return (l+r)%mod*((r-l+1)%mod)%mod*inv2%mod;}
inline int get(int x){return x%mod*((2*x+1)%mod)%mod*((x+1)%mod)%mod*inv6%mod;}
inline int get2(int l,int r){return (get(r)-get(l-1)+mod)%mod;}
inline void gan1(){cout<<n%mod<<endl;exit(0);}
inline void gan2()
{
int ans=0;
for(int l=1,r;l<=n;l=r+1)
{
r=n/(n/l);
ans=(ans+(r-l+1)%mod*(n/l-1)%mod)%mod;
}
cout<<ans<<endl;
exit(0);
}
inline void gan3()
{
cout<<n%mod*((n-1)%mod)%mod*inv2%mod<<endl;
exit(0);
}
inline void gan4(){cout<<(n/3)%mod<<endl;exit(0);}
inline void gan5()
{
int ans=0;
for(int l=1,r;l<=n;l=r+1)
{
r=n/(n/l);
int sum=(get1(l,r)-(r-l+1)%mod-(r/2-(l-1)/2)%mod+2*mod)%mod*inv2%mod;
ans=(ans+(n/l)%mod*sum%mod)%mod;
}
cout<<ans<<endl;
exit(0);
}
inline void gan6()
{
cout<<(n%mod)*((n-1)%mod)%mod*((n-2)%mod)%mod*inv6%mod;
exit(0);
}
inline void gan7()
{
int ans=0;
if(n==4||n==5)ans=1;
else ans=(n/6+n/9+n/10+n/12+n/15+n/21)%mod;
cout<<ans<<endl;
exit(0);
}
inline void gan8()
{
int ans=0;
if(n<=6)ans=1;else if(n==7)ans=3;else if(n==8)ans=6;else if(n==9)ans=9;else if(n==10)ans=10;
else ans=(n/11+n/29)%mod;
cout<<ans<<endl;
exit(0);
}
inline void gan9()
{
int ans=0;
if(n==4)ans=1;else if(n==5)ans=5;
else
{
for(int l=1,r;l<=n;l=r+1)
{
r=n/(n/l);
int sum=(get2(l,r)-6*get1(l,r)%mod+5*(r-l+1)%mod+3*((r/2)-(l-1)/2)%mod+4*((r/3)-(l-1)/3)%mod+mod)%mod*inv2%mod*inv6%mod;
ans=(ans+(n/l)%mod*sum%mod)%mod;
}
}
cout<<ans<<endl;
exit(0);
}
inline void gan10()
{
cout<<(n%mod)*((n-1)%mod)%mod*((n-2)%mod)%mod*((n-3)%mod)%mod*inv24%mod;
exit(0);
}
signed main()
{
freopen("vegetable.in","r",stdin);
freopen("vegetable.out","w",stdout);
cin>>n>>m>>k;
if(m==1&&k==1)gan1();if(m==2&&k==1)gan2();if(m==2&&k==2)gan3();
if(m==3&&k==1)gan4();if(m==3&&k==2)gan5();if(m==3&&k==3)gan6();
if(m==4&&k==1)gan7();if(m==4&&k==2)gan8();if(m==4&&k==3)gan9();
if(m==4&&k==4)gan10();
return 0;
}
最后一句,考场上咋办?
打表啊孩子!
标签:int,分类,毒瘤,枚举,子集,2a,&&,数学题,mod 来源: https://www.cnblogs.com/PMZG/p/15376763.html