zoukankan      html  css  js  c++  java
  • codeforces 258C Little Elephant and LCM 组合数学 枚举

    题意:

    input :

    a1,a2,...,an

    1 <= n <= 10^5

    1 <= ai <= 10^5

    求b数组的方案数,b数组满足:

    1. 1 <= bi <= ai

    2. lcm(bi) = max(bi)

    solution:

    2说明了b数组的每一个元素都是max(bi)的约数

    则:

    1.sort a数组,ma  = a[n]

    2.预处理2个数组,vector<int> dive[MAXN],int pos[MAXN]

    dive[i]保存i的约数,并且按照小到大排序

    sort(dive[i].begin(),dive[i].end())

    pos[i]表示a数组中 >= i 的数的最小位置

    3.枚举max(bi):1~ma,则:

    ans = sigma( dive(i).size()^(n - pos[i]+1) - (dive[i].size()-1)^(n-pos[i]+1) *

        sigma((j+1)^(pos[dive[i][j+1]])-pos[dive[i][j]]),0<=j<dive[i].size() ),1<=i<=ma

    推这条公式其实就是枚举max为i,然后把b数组分成若干段,每一个段的可以选择的数就是dive[i]的部分约数,先把dive[i]排序后,可以知道每一个段可以选择的数的个数,就得到公式了。

                                                
      //File Name: cf258C.cpp
      //Author: long
      //Mail: 736726758@qq.com
      //Created Time: 2016年02月23日 星期二 18时30分26秒
                                       
    
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <iostream>
    #include <vector>
    #include <cmath>
    #include <map>
    
    #define LL long long 
    #define pb push_back
    
    using namespace std;
    
    const int MAXN = (int)1e5+5;
    const int MOD = (int)1e9+7;
    
    int a[MAXN];
    vector<int> dive[MAXN];
    int pos[MAXN];
    int ma;
    
    LL qp(LL x,LL y)
    {
        LL res = 1LL;
        while(y){
            if(y & 1)
                res = res * x % MOD;
            x = x * x % MOD;
            y >>= 1;
        }
        return res;
    }
    
    void get_dive(int x)
    {
        for(int i=1;i<=x;i++){
            dive[i].clear();
            int e = (int)sqrt(i + 0.0);
            for(int j=1;j<=e;j++){
                if(i % j == 0){
                    dive[i].pb(j);
                    if((i / j) != j)
                        dive[i].pb(i / j);
                }
            }
            sort(dive[i].begin(),dive[i].end());
        }
    }
    
    int bs(int l,int r,int x)
    {
        int mid;
        while(r - l > 1){
            mid = (l + r) >> 1;
            if(a[mid] < x)
                l = mid;
            else
                r = mid;
        }
        if(a[l] >= x)
            return l;
        return r;
    }
    
    void solve(int n)
    {
        sort(a+1,a+n+1);
        ma = a[n];
        get_dive(ma);
        pos[1] = 1;
        for(int i=2;i<=ma;i++){
            pos[i] = bs(pos[i-1],n,i);
        }
        LL ans = 0LL;
        LL tmp;
        for(int i=1;i<=ma;i++){
            int x = n - pos[i] + 1;
            int y = (int)dive[i].size();
            tmp = (qp(y,x) - qp(y-1,x) + MOD) % MOD;
            for(int j=0;j<dive[i].size() - 1;j++){
                tmp = tmp * qp(j+1,pos[dive[i][j+1]] - pos[dive[i][j]]) % MOD;
            }
            ans = (ans + tmp) % MOD;
        }
        printf("%d
    ",(int)ans);
        return ;
    }
    
    int main()
    {
        int n;
        while(~scanf("%d",&n)){
            for(int i=1;i<=n;i++){
                scanf("%d",&a[i]);
            }
            solve(n);
        }
        return 0;
    }
  • 相关阅读:
    NSPredicate
    label 下划线加自动换行
    【搬运】快速增加文档注释
    NSSortDescriptor 数组排序
    【搬运】打开模拟器沙盒目录
    NSTimer 详解
    Android打开外部DB文件
    图片压缩与缓存
    StartService与BindService
    Android发送通知栏通知
  • 原文地址:https://www.cnblogs.com/-maybe/p/5557413.html
Copyright © 2011-2022 走看看