【无标题】

一.整数分解的唯一性与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<bits/stdc++.h>
#include<iostream>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<cstring>
#include<math.h>
#include<map>
#include<vector>
#include<stack>
#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 gcd(int a, int b) {                    //辗转相除法求最大公约数
    return !b ? a : gcd(b, a % b);
}
void solve() {
    int a, a1, b, b1;
    cin >> a >> a1 >> b >> b1;
    int ans = 0;
    int x = b1;
    set<int>s;
    for (int i = 1; i * i <= x; i++) {                //找出最大公倍数的因子
        if (x % i == 0) {
            s.insert(i);
            s.insert(x / i);
        }
    }
    for (auto y : s) {                        //枚举因子
        if (y % a1 == 0 && gcd(y / a1, a / a1) == 1 && gcd(b1 / y, b1 / b) == 1) {
            ans++;
        }
     }
     cout << ans << '\n';
 }
signed main()
{
    ios;
    int t=1;
    cin >> t;
    while (t--) {
        solve();
    }
}

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<Di,ans=0
2.Bi=Di,ans不变
3.Bi>Di,ans=ans*2
 

#include<iostream>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<cstring>
#include<math.h>
#include<map>
#include<vector>
#include<stack>
#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<iostream>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<cstring>
#include<math.h>
#include<map>
#include<vector>
#include<stack>
#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<iostream>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<cstring>
#include<math.h>
#include<map>
#include<vector>
#include<stack>
#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;
    map<int, int>mp;
    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<bits/stdc++.h>
#include<iostream>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<cstring>
#include<math.h>
#include<map>
#include<vector>
#include<stack>
#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();
    }
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值