每天写一道数学题挑战
不出意外的话到 csp 之前都会持续更新。
前言
看到有的人 在 挑 战,我看了看也决定挑战一下每天写一道 数 学 题。从 8.11 号开始更新,不出意外的话一个月应该能写 30 道 数学 题,出意外的话应该会写 28 道或 31 道,放到博客上也是为了大家共同监督,加油吧
Day 1
8.11
闲话:今天早上看到 奇怪的博引发了我(和eafoo)写这
玩意的兴趣。
然而eafoo在第一天就完结撒花了。
不过, 你们以为我要鸽,其实我没有鸽,这其实也是一种鸽。
所以我不咕了。
以及:今天早上洛谷打卡大吉,宜考试。
然后模拟赛罚坐四小时一个部分分不会惨遭保龄
P6672 你的生命已如风中残烛
前置芝士
Raney 定理(的一种表述形式):有 n 个数(有标号,数权值可能相同,但权值相同标号不同的数视为不同),若这 n 个数的权值和为 1,则它的一个圆排列的 n 种断环成链的方案中,有且仅有一种方案能使形成的排列的任意前缀和为正数。
也就是说,权值和为 1 的 n 个数的能使任意前缀和为正数的排列数为它的圆排列数,即\((n-1)!\)
应用
我们把 m 张牌的 w 值都减去 1
现在,要求的就是 满足 \(\sum_{i=1}^m=0\) 的序列w, 有多少个排列满足任意前缀和非负
我们在序列中插一个-1,然后全部取反,就变成了求 满足 \(\sum_{i=1}^m=1\) 的序列w, 有多少个排列满足任意前缀和为正
另外,因为多加了一个-1形成的-1排列为\((m-n+1)!\),而不多加-1形成的是\((m-n)!\),因此我们多算了(m-n+1)倍。
答案为 \(\frac{m!}{m-n+1}\)
代码
~ (=_= ?)
#include <bits/stdc++.h> using namespace std; #define int long long const int mod =998244353; int fsp(int a,int b) { int s=1; while(b) { if(b&1)s=s*a%mod; b>>=1; a=a*a%mod; } return s; } signed main() { int n; cin>>n; int m=0; int s=1; for(int i=1;i<=n;i++) { int x; cin>>x; m+=x; } for(int i=1;i<=m;i++) { s=s*i%mod; } s=s*fsp(m-n+1,mod-2)%mod; cout<<s<<endl; return 0; }
颜文字是自己发明的。
Day 2
P5221 Product
代码
~ (=_= ?)
#include<bits/stdc++.h> using namespace std; #define LL long long const LL mod = 104857601; const LL Mod = 104857600; const int maxn = 1e6+100; int prime[maxn],cnt,phi[maxn]; bool vis[maxn]; void init(int n) { vis[1]=phi[1]=1; for(int i=2;i<=n;i++) { if(!vis[i]) { prime[++cnt]=i; phi[i]=i-1; } for(int j=1;j<=cnt&&prime[j]*i<=n;j++) { vis[prime[j]*i]=1; if(i%prime[j]) { phi[prime[j]*i]=(prime[j]-1)*phi[i]; }else{ phi[prime[j]*i]=prime[j]*phi[i]; break; } } } for(int i=1;i<=n;i++) { phi[i]=(phi[i-1]+phi[i])%Mod; } } long long fsp(long long a,long long b) { long long s=1; while(b) { if(b&1) { s=s*a%mod; } b>>=1; a=a*a%mod; } return s; } int main() { long long fc=1; int n; cin>>n; init(n); for(int i=1;i<=n;i++) { fc=fc*i%mod; } fc=fsp(fc,2*n); long long s=1; for(int i=1;i<=n;i++) { s=s*fsp(i,((2*phi[n/i]-1)%Mod+Mod)%Mod)%mod; } cout<<fc*fsp(s,mod-3)%mod; return 0; }
Day 3 Day 4 Day 5
幽灵乐团type0,1,2
~ (=_= ?)
#include <bits/stdc++.h> using namespace std; #define LL long long const int maxn = 1e5 + 5; const int maxv = 1e5; int fac[maxn], prime[maxn], cnt, vis[maxn], mu[maxn], sum[maxn], f1[maxn], sum1[maxn], mul2[maxn], f2[maxn], sum2[maxn], phi[maxn],inv[maxn]; int P, P1; int d[maxn]; int fsp(int a, int b, int mod) { int s = 1; while (b) { if (b & 1) s = 1ll * s * a % mod; b >>= 1; a = 1ll * a * a % mod; } return s; } void init() { vis[1] = mu[1] = phi[1] = 1; for (int i = 2; i <= maxv; i++) { if (!vis[i]) { prime[++cnt] = i; mu[i] = -1; phi[i] = i - 1; } for (int j = 1; j <= cnt && i * prime[j] <= maxv; j++) { vis[i * prime[j]] = 1; if (i % prime[j] == 0) { phi[i * prime[j]] = phi[i] * prime[j]; break; } else { mu[i * prime[j]] = -mu[i]; phi[i * prime[j]] = phi[i] * (prime[j] - 1); } } } fac[0] = sum1[0] = mul2[0] = sum2[0] = 1; for (int i = 1; i <= maxv; i++) { fac[i] = 1ll * fac[i - 1] * i % P; sum[i] = (sum[i - 1] + phi[i]) % P1; mul2[i] = (1ll * mul2[i - 1] * fsp(i, i, P)) % P; d[i] = (d[i - 1] + i) % P1; f1[i] = f2[i] = 1; } for (int i = 1; i <= maxv; i++) { for (int j = 1; j * i <= maxv; j++) { int T = i * j; f1[T] = 1ll * f1[T] * fsp(i, (mu[j] + P1) % P1, P) % P; f2[T] = 1ll * f2[T] * fsp(i, 1ll * T * T % P1 * (mu[j] + P1) % P1, P) % P; } } inv[0]=1; for (int i = 1; i <= maxv; i++) { sum1[i] = (1ll * sum1[i - 1] * f1[i]) % P; sum2[i] = (1ll * sum2[i - 1] * f2[i]) % P; inv[i]=fsp(sum1[i],P-2,P); } } int block_f1(int N, int M) { if (N > M) swap(N, M); int l = 1, r = 0, ans = 1; for (; l <= N;) { r = min((N / (N / l)), M / (M / l)); int tmp = 1ll * sum1[r] * inv[l-1] % P; tmp = fsp(tmp, 1ll * (M / l) * (N / l) % P1, P); ans = 1ll * ans * tmp % P; l = r + 1; } return ans; } int block_f2(int N, int M) { if (N > M) swap(N, M); int l = 1, r = 0, ans = 1; for (; l <= N;) { r = min((N / (N / l)), M / (M / l)); int tmp = 1ll * sum2[r] * fsp(sum2[l - 1], P - 2, P) % P; tmp = fsp(tmp, 1ll * d[(M / l)] * d[(N / l)] % P1, P); ans = 1ll * ans * tmp % P; l = r + 1; } return ans; } int solve1(int A, int B, int C) { int ans = 1ll * fsp(fac[A], B, P) * fsp(fac[B], A, P) % P; ans = fsp(ans, C, P); LL tmp1 = 1, tmp2 = 1; tmp1 = block_f1(A, B); tmp2 = block_f1(A, C); tmp1 = fsp(tmp1, C, P); tmp2 = fsp(tmp2, B, P); ans = 1ll * ans * fsp(1ll * tmp1 * tmp2 % P, P - 2, P) % P; return (ans % P + P) % P; } int solve2(int A, int B, int C) { int ans = 1ll * fsp(mul2[A], 1ll * d[B] * d[C] % P1, P) * fsp(mul2[B], 1ll * d[A] * d[C] % P1, P) % P; LL tmp1 = 1, tmp2 = 1; tmp1 = block_f2(A, B); tmp2 = block_f2(A, C); tmp1 = fsp(tmp1, d[C], P); tmp2 = fsp(tmp2, d[B], P); ans = 1ll * ans * fsp(1ll * tmp1 * tmp2 % P, P - 2, P) % P; return ans; } int block_f3(int N, int M, int K) { int l = 1, r = 0, ans = 1; for (; l <= N;) { if(l>M)break; if(l>K)break; r = min((N / (N / l)), min(M / (M / l), K / (K / l))); if(r>M)r=M; if(r>K)r=K; int tmp = solve1(N/l,M/l,K/l); tmp = fsp(tmp, (sum[r]-sum[l-1]+P1)%P1, P); ans = 1ll * ans * tmp % P; l = r + 1; } return ans; } int solve3(int A, int B, int C) { int ans = block_f3(A,B,C); return ans; } int main() { int T; cin >> T >> P; P1 = P - 1; init(); while (T-- > 0) { int A, B, C; cin >> A >> B >> C; cout << solve1(A, B, C) << " " << solve2(A, B, C) << " " << solve3(A, B, C) << endl; } return 0; }
Day 6
P5176 公约数
代码
~ (=_= ?)
#include <bits/stdc++.h> using namespace std; #define LL long long #define maxn 20000005 int prime[4000005],cnt,n; bool vis[maxn]; LL mu[maxn],f[maxn]; const LL mod = 1e9+7; void oula(int n) { mu[1]=vis[1]=f[1]=1; for(int i=2;i<=n;i++) { if(!vis[i]) { prime[++cnt]=i; mu[i]=-1; f[i]=(1ll*i*i-1)%mod; } for(int j=1;j<=cnt&&i*prime[j]<=n;j++) { vis[i*prime[j]]=1; if(i%prime[j]) { mu[i*prime[j]]=-mu[i]; f[i*prime[j]]=f[i]*f[prime[j]]%mod; }else { mu[i*prime[j]]=0; f[i*prime[j]]=f[i]*prime[j]%mod*prime[j]%mod; break; } } } for(int i=1;i<=n;i++) { f[i]=(f[i-1]+f[i])%mod; } } const LL inv6=166666668; LL calc(LL n,LL m) { int l,r; LL sum=0; for(l=1;l<=min(n,m);l=r+1) { r=min(n/(n/l),m/(m/l)); sum+=1ll*(f[r]-f[l-1]+mod)%mod*(n/l)%mod*(m/l)%mod; sum%=mod; } return sum; } int main() { int T; scanf("%d",&T); oula(20000000); while(T --> 0) { int a,b,c; cin>>a>>b>>c; LL ans=(a*calc(b,c)+b*calc(a,c)+c*calc(a,b))%mod; cout<<ans<<endl; } return 0; }