费马小定理
定义
若 a a a 与 p p p 互质(即 gcd ( a , p ) = 1 \gcd(a,p)=1 gcd(a,p)=1),则:
a p − 1 ≡ 1 ( m o d p ) a^{p-1}\equiv1\pmod p ap−1≡1(modp)
根据上述公式我们还可以推出一个公式:
a p − 2 ≡ a − 1 ( m o d p ) a^{p-2}\equiv a^{-1}\pmod p ap−2≡a−1(modp)
使用条件: p p p 需为质数。
也就是逆元。
常用来解决有除法且需要取模的问题(除法不能取模)。
应用
P10792 『SpOI - R1』笑起来最帅的小孩
期望+逆元。
比如说我们有 1 1 1 个 2 2 2, 2 2 2 个 1 1 1,考虑所有情况:
112
112
121
121
211
211
加起来为 888 888 888。
数据小的情况可以直接手动例举,但如果数据大了呢?
考虑直接计算每一位的贡献。
比如说第一个 1 1 1 在各位上的贡献为 2 ! 2! 2!,十位为 10 × 2 ! 10\times 2! 10×2!,百位为……
总共贡献: 111 × 2 ! 111\times 2! 111×2!。
即 ( 1 0 n − 1 ) × 2 ! (10^n-1)\times 2! (10n−1)×2!。
n n n 表示数列的长度。
以此类推,所有数字的贡献总和为:
( ∑ i = 1 k x i × l i ) × ( 1 0 n − 1 ) × ( n − 1 ) ! (\sum_{i=1}^k x_i\times l_i)\times (10^n-1)\times (n-1)! (i=1∑kxi×li)×(10n−1)×(n−1)!
然后还要对贡献和除以 n ! n! n!,公式为:
( ∑ i = 1 k x i × l i ) × ( 1 0 n − 1 ) n \frac{(\sum_{i=1}^k x_i\times l_i)\times (10^n-1)}{n} n(∑i=1kxi×li)×(10n−1)
接下来用逆元解决就好了。
实现
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int mod=2007072007;
int t,k,x[100005],l[100005];
int kpow(int a,int b){int sum=1;while(b){if(b&1){sum=(sum*a)%mod;}a=(a*a)%mod;b/=2;}return sum;
}
signed main(){ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);for(cin>>t;t;t--){cin>>k;int n=0,sum=0;for(int i=1;i<=k;i++){cin>>x[i]>>l[i];n=(n+l[i])%mod,sum=(sum+x[i]*l[i])%mod;}cout<<(((((sum*(kpow(10,n)-1))%mod)*kpow(9,mod-2))%mod)*kpow(n,mod-2))%mod<<'\n';}return 0;
}