一.整数分解的唯一性与gcd,lcm
1.
P1072[NOIP2009 提高组] Hankson 的趣味题
题意:已知a,a1,b,b1 x与a的的最大公约数是a1,x与b的最大公倍数是b1
求解有多少满足的x
思路:
gcd(x,a)=a1,x=k1a1,a=k2a1,gcd(k1,k2)=1
反证:gcd(k1,k2)=k(k!=1),k1=kp,k2=kq ->x=kk1a1,a=kk2a1,gcd(x,y)=ka1
结论进一步可推得:对于两个正整数a,b,若gcd(a,b)=k,gcd(a/k,b/k)=1
lcm(x,b)=b1 => x*b/gcd(x,b)=b1 =>gcd(x,b)=x*b/b1 => gcd(b1/b,b1/x)=1
结论进一步可推得:对于两个正整数a,b,若lcm(a,b)=k,gcd(k/a,k/b)=1
#include
#include
#include
#include
2.
cf1866/problem/B
给定两个数x,y的的质因数分解式Ai,Bi表示x的质数,指数;Ci,Di表示y的质数,指数
求有多少对p,q满足lcm(p,q)=x,gcd(p,q)=y
思路1.p*q=x*y 2.对于某个质数的指数,gcd相当于取min,lcm相当于取max
对于某个素数,
1.若Bi
3.Bi>Di,ans=ans*2
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define endl '\n'
#define ios ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr)
#define ms(x,y) memset(x,y,sizeof x);
#define YES cout<<"YES"<<'\n';
#define NO cout<<"NO"<<'\n';
#define fr(i,z,n) for(int i = z;i <= n; i++)
#define ufr(i,n,z) for(int i = n;i >= z; i--)
typedef long long ll;
const int N = 2000005, mod = 998244353;
using namespace std;
int a[N];
int b[N];
int c[N];
int d[N];
int mp1[N];
int mp[N];
void solve() {
int n;
cin >> n;
fr(i, 1, n) {
cin >> a[i];
}
fr(i, 1, n) {
cin >> b[i];
mp1[a[i]] = b[i];
}
int m;
cin >> m;
fr(i, 1, m) {
cin >> c[i];
}
fr(i, 1, m) {
cin >> d[i];
mp[c[i]] = d[i];
}
int ans = 1;
for (int i = 1; i <= 2000000; ++i){
if (mp1[i] < mp[i]) {
cout << 0 << '\n';
return;
}
else if (mp1[i] > mp[i]) {
ans *= 2;
ans %= mod;
}
}
cout << ans%mod << '\n';
}
signed main()
{
ios;
int t = 1;
//cin >> t;
while (t--) {
solve();
}
}
3.
P1593 因子和
求a^b得因子和,对出它对 9901 取模的结果
a<=5e7,b<=5e7
思路:推导过程:整数的唯一分解定理,对a进行质因数分解
a=p1^k1 *p2^k2 *p3^k3 ...*pn^kn->对a^b进行质因数分解
a^b=p1^(k1*b) *p2^(k2*b)...*pn^(kn*b)
因子和求解 ans=(1+p1^1+p1^2...p1^(k1*b))*(1+p2^1+p2^2...p2^(k2*b)*...*(1+pn^1+pn^2...pn^(n*b)
等比数列求和qi^n-1/qi-1相乘
除法逆元
当qi-1与mod互质时,逆元为pow(qi-1,mod-2)
不互质时,(p-1)%mod==0,p%mod==1,->(1+pi^1+pi^2...pi^(k1*b))%mod->1+k1*b
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define endl '\n'
#define ios ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr)
#define ms(x,y) memset(x,y,sizeof x);
#define YES cout<<"YES"<<'\n';
#define NO cout<<"NO"<<'\n';
#define fr(i,z,n) for(int i = z;i <= n; i++)
#define ufr(i,n,z) for(int i = n;i >= z; i--)
#define int long long
typedef long long ll;
const ll maxn=2e5+10,inf = 1e18 ;
const ll mod = 9901;
using namespace std;
int mp[10010][2];
ll poww(ll x, ll k) {
if (k == 1) return x;
if (k == 0) return 1;
ll tmp = poww(x, k / 2);
if (k & 1) return tmp * tmp % mod * x % mod;
return tmp * tmp % mod;
}
void solve() {
int a, b;
cin >> a >> b;
if (a== 0) { //特判
cout << 0 << '\n';
return;
}
int cnt = 0;
for (int i = 2; i * i <= a; i++) {
if (a % i == 0) {
mp[++cnt][0]=i;
mp[cnt][1] = 1;
a /= i;
while (a % i == 0) {
mp[cnt][1]++;
a /= i;
}
}
}
if (a != 1) {
mp[++cnt][0] = a;
mp[cnt][1]++;
}
int ans = 1;
fr(i, 1, cnt) {
int x = mp[i][0];
int y = mp[i][1];
if (x%mod==1) {
ans = ans%mod * ( y * b + 1) % mod;
}
else { //互质
ans = ans%mod * (((poww(x, (y * b + 1) % mod)) - 1 + mod) % mod) * (poww((x - 1+mod)%mod, mod - 2) % mod);
}
}
cout << (ans%mod+mod)%mod<< '\n';
}
signed main(){
ios;
int t=1;
//cin >> t;
while (t--) {
solve();
}
}
4.
P1414 又是毕业季II
题意:老师给每位同学评了一个能力值。从n个学生中挑出k个人使得他们的默契程度(即能力值的最大公约数)最大
总共 n 行,第i 行为k=i情况下的最大默契程度。
n<=10^4,m<=10^6
k个数中最大公约数:k个数中共有的因子最大的
于是可以将所有数的因子找出并记录个数
因为因子值越小,个数越多,满足单调性,记录最大值,不断缩小直到个数大于等于k
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define endl '\n'
#define ios ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr)
#define ms(x,y) memset(x,y,sizeof x);
#define YES cout<<"YES"<<'\n';
#define NO cout<<"NO"<<'\n';
#define fr(i,z,n) for(int i = z;i <= n; i++)
#define ufr(i,n,z) for(int i = n;i >= z; i--)
typedef long long ll;
const ll maxn = 2e5 + 10, inf = 1e18;
const ll mod = 1e9 + 7;
using namespace std;
int a[maxn];
void solve() {
int n;
cin >> n;
mapmp;
int Max = 0;
fr(i, 1, n) {
cin >> a[i];
Max = max(Max, a[i]);
for (int j = 1; j *j <= a[i]; j++) {
if (a[i] % j == 0) {
mp[j]++;
if (j* j != a[i]) {
mp[a[i]/j]++;
}
}
}
}
fr(i, 1, n) {
while (mp[Max] < i) Max--;
cout << Max << '\n';
}
}
signed main()
{
ios;
int t = 1;
//cin >> t;
while (t--) {
solve();
}
}
二。组合数恒等式 ->杨辉三角
P2822[NOIP2016 提高组] 组合数问题
题意:给定n,m,k,对于所有的0<=i<=n,0<=j<=min(i,m),有多少对C(j,i)%k==0
思路:
1.组合数公式 50分
2.组合恒等式 C(n,m)=C(n-1,m-1)+C(n-1,m)->杨辉三角(n相当于行,m相当于列,每个数等于上方两数之和)
杨辉三角的第n行的m个数可表示为 C(n-1,m-1),即为从n-1个不同元素中取m-1个元素的组合数。
预处理出杨辉三角,然后对每个数%k,二维前缀和,特殊的对于每行比上一行多出的进行处理
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define endl '\n'
#define ios ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr)
#define ms(x,y) memset(x,y,sizeof x);
#define YES cout<<"YES"<<'\n';
#define NO cout<<"NO"<<'\n';
#define fr(i,z,n) for(int i = z;i <= n; i++)
#define ufr(i,n,z) for(int i = n;i >= z; i--)
typedef long long ll;
const ll maxn=2e5+10,inf = 1e18 ;
const ll mod = 1e9 + 7;
using namespace std;
int a[maxn];
int c[2005][2005];
int s[2005][2005]; //记录矩阵前缀和
int t, k;
void init() {
c[1][1] = 1;
fr(i, 0, 2000) {
c[i][0] = 1;
}
fr(i, 2, 2000) {
fr(j, 1, i) {
c[i][j] = (c[i - 1][j - 1] + c[i - 1][j])%k;
}
}
//fr(i, 1, 10) {
// fr(j, 0, i) {
// cout << c[i][j] << ' ';
// }
// cout << '\n';
//}
fr(i, 1, 2000) {
fr(j, 1, i) {
s[i][j] = s[i][j] + s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1]; //二维前缀和
if (c[i][j] == 0) s[i][j] += 1;
}
s[i][i] = s[i][i - 1];
}
/*fr(i, 1, 10) {
fr(j, 1, i) {
cout << s[i][j] << ' ';
}
cout << '\n';
}*/
}
void solve(){
cin >> t >> k;
init();
fr(i, 1, t) {
int n, m;
cin >> n >> m;
if (m > n) m = n;
cout << s[n][m] << '\n';
}
}
signed main()
{
ios;
int t=1;
//cin >> t;
while (t--) {
solve();
}
}