问题 A: Indivisibility
题目描述
给一个数n,找出1 ~ n范围内不被2 ~ 10整除的数的个数
输入
一个数n
输出
1 ~ n范围内不被2 ~ 10整除的数的个数
样例输入 Copy
12
样例输出 Copy
2
提示
数据范围:1<=n<=10^18
思路:
一共有n个数,这个题我们很容易想到,只需要减去那些不符合条件的就可以了
2 ~ 10之间的数可以分成被2 3 5 7整除的数
所以问题就转化成减去被2 3 5 7整除的数
我们可以得到ans = n - n/2 - n/3 - n/5 - n/7
我们又发现有一些数可以被2 3 5 7中的两个数整除
但是这样的数在前面多减了一次
比如6,它既可以被2整除也可以被3整除,它在n/2中减去一次,在n/3中又减去一次,所以我们需要加回来
ans = ans + n/(2 * 3) + n/(2 * 5) + n/(2 * 7) + n/(3 * 5) + n/(3 * 7) + n/(5 * 7)
同理可以被2 3 5 7中三个数整除的数在第一次中减去三次,在第二次中又加回来三次,相当于没有改变,所以我们还需要减去这一部分
比如30,它可以被2 3 5整除,它在n/2 n/3 n/5中各减去一次,一共减了三次,又在 n/(2 * 3) n/(2 * 5) n/(3 * 5) 加回来三次,所以我们需要再减去一次才符合条件
ans = ans - n/(2 * 3 * 5) - n/(2 * 3 * 7) - n/(2 * 5 * 7) - n/(3 * 5 * 7)
最后我们再减去可以被2 3 5 7四个数整除的就可以了
ans = ans - n/(2 * 3 * 5 * 7)
ll n,ans;
int main()
{
scanf("%lld",&n);
ans = n-(n/2+n/3+n/5+n/7)+n/6+n/10+n/14+n/15+n/21+n/35-(n/30+n/42+n/70+n/105)+n/210;
printf("%lld\n",ans);
return 0;
}
问题 B: Kuroni and Impossible Calculation
题目描述
已知一个数组a[n],请计算式子:∏_{1≤i
输入
第一行是n,m。第二行是n个整数:a[1],a[2]……a[n]
输出
输出 ∏1≤i
3 12
1 4 5
样例输出 Copy
0
提示
数据范围: 2≤n≤2⋅10^5, 1≤m≤1000,0≤ai≤10^9
思路:
我们发现模数m很小所以这个题可以用到鸽笼原理
鸽笼原理 (抽屉原理) “如果有五个鸽子笼,养鸽人养了6只鸽子,那么当鸽子飞回笼中后,至少有一个笼子中装有2只鸽子。”
当n > m 的时候,一定存在a[i] ≡ a[j] (mod m),所以答案就是0
当n <= m 的时候,暴力解决就可以了
int n,m;
ll a[maxn];
int main()
{
n = read(),m = read();
for(int i=1;i<=n;i++) cin >> a[i];
ll ans = 1;
if(n <= m)
{
for(int i=1;i<=n;i++)
{
for(int j=i+1;j<=n;j++)
{
ans = (ans*abs(a[j]-a[i])%m) % m;
}
}
cout << ans << endl;
}
else printf("0\n");
return 0;
}
问题 D: 排课表
题目描述
新学期伊始,作为玉米高中的教务主任W某,又要安排学生们的课程表了。
W某想要知道所有可能的排课表方案,于是他开始在纸上列举所有方案,然而在写满了一摞A4纸后,他发现可能的方案太多了——用尽玉米高中所有的A4纸都写不完。
W某最终放弃了列举所有方案的想法,但他对排课表的方案数产生了兴趣。他的组合数学不太好,所以他找到了正在玉米高中就读的你,请你帮帮TA。
简单地说,玉米高中共有T个班级。
对于其中一个班级i,这个班级每天要上mi节互不相同的课,一共有ni节课可供选择,但这ni节课不能随便安排,其中也有一些限制:
·有ai节课不能安排在第一节上
·有bi节课不能安排在最后一节上
·没有任何一节课既不能在第一节上又不能在最后一节上
你需要求出每个班级排课表的方案数除以998244353的余数。
输入
第1行包含一个正整数T,表示玉米高中的班级数。
第2行到第T+1行,每行包含四个整数,第i+1行的四个整数ni,mi,ai,bi,分别表示班级i可选的课程数,一天的课程数,不能在第一节上的课程数,不能在最后一节上的课程数。
输出
输出T行,第i行表示班级i的排课表方案数除以998244353的余数。
样例输入 Copy
【样例1】
1
3 2 0 1
【样例2】
1
5 3 1 1
样例输出 Copy
【样例1】
4
【样例2】
39
提示
样例1解释
设3节可选的课为a,b,c,其中c不能排在最后一节
4种排课表的方案分别为:ab,ba,ca,cb
所有测试数据满足
·1≤T≤104
·2≤mi≤ni≤105
·ai+bi≤ni
const int N = 100010;
const int mod = 998244353;
/** keep hungry and keep calm! **/
ll ans;
int t,n,m,a,b;
ll fac[N];//阶乘
ll ni[N];//逆元
ll power(ll a,ll b,ll p)//快速幂
{
ll ans = 1,base = a;
while(b)
{
if(b & 1)
//&运算当相应位上的数都是1时,该位取1,否则该为0
ans = 1ll*ans*base % p;
base = 1ll*base*base % p;
b >>= 1;//十进制下每除10 整数位就退一位
}
return ans;
}
void init()
{
fac[0] = 1;
ni[0] = 1;
for(int i=1; i<N; i++)
{
fac[i] = fac[i-1]*i % mod;//求阶乘
ni[i] = ni[i-1]*power(i,mod-2,mod) % mod;
}
}
int main()
{
init();
cin >> t;
while(t--)
{
cin >> n >> m >> a >> b;
ans = (fac[n]%mod*ni[n-m]%mod-fac[n-1]%mod*ni[n-m]%mod*(a+b)%mod+fac[n-2]%mod*ni[n-m]%mod*a*b%mod) % mod;
if(ans < 0) ans += mod;
cout << ans << endl;
}
return 0;
}