ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Codeforces Round #813 (Div. 2) A - E2

2022-08-27 03:00:39  阅读:163  来源: 互联网

标签:lcm int Codeforces len cin while solve Div 813


A:一组长度为n 的排列,问交换多少次,能让前m个数变成[1,m]中的数

输出前 m 个数中有多少个比 m 大的就可以了

//-------------------------代码----------------------------
 
//#define int ll
const int N = 1e5+10;
int n,m;
 
void solve()
{
    cin>>n>>m;
    int ans = 0;
    set<int> q;
    fo(i,1,n) {
        int x;cin>>x;
        if(i <= m) {
            if(x > m) {
                ans ++ ;
            }
        }
    }
    cout<<ans<<endl;
}
void main_init() {}
signed main(){
    AC();clapping();TLE;
    cout<<fixed<<setprecision(12);
    main_init();
//  while(cin>>n,n)
//  while(cin>>n>>m,n,m)
    int t;cin>>t;while(t -- )
    solve();
//    {solve(); }
    return 0;
}
 
/*样例区
 
 
*/
 
//------------------------------------------------------------

B:一组长度为n的数,让所有数的位置和值的lcm之和最大

位置大的和值大的lcm如果不是本身一般就是最大的。

知识:x和x+1互质。所以只要 将n 个数两两互换就可以了

需要注意,如果有奇数个数,第一个数只能是1,偶数个数,第一个数只能是2

 

//-------------------------代码----------------------------
 
//#define int ll
const int N = 1e5+10;
int n,m;
int a[N];
void solve()
{
    cin>>n;
    for(int i = n;i>=1;i-=2) {
        a[i] = i - 1;a[i-1] = i;
    }
    if(n % 2 == 1) a[1] = 1;
    else a[1] = 2;
    fo(i,1,n) cout<<a[i]<<' ';cout<<endl;
}
void main_init() {}
signed main(){
    AC();clapping();TLE;
    cout<<fixed<<setprecision(12);
    main_init();
    int t;cin>>t;while(t -- )
    solve();
    return 0;
}
 
/*样例区
 
 
*/
 
//------------------------------------------------------------

C:n个数,问删除多少种数,可以使序列递增

从前往后遍历,如果当前数出现两次以上,并且不相邻,就要删掉所有数的种数

如果当前数比后面的数大,也要删掉所有数的种数

取一个删去种数的最大值就好了

前k 个数有多少种数怎么算?将所有数放到set里会自动去重,算set的大小就可以了

 

//-------------------------代码----------------------------
 
//#define int ll
const int N = 1e5+10;
int n,m;
int a[N];
void solve()
{
    cin>>n;
    int mx = 0;
    map<int,int> mp; 
    set<int> q;
    fo(i,1,n) {
        cin>>a[i];
        mp[a[i]] ++ ;
        if(i >= 2 && mp[a[i]] >= 2 && a[i-1] != a[i]) mx = max(int(q.size()),mx);
        if(i >= 2 && a[i] < a[i-1]) mx = max((int)q.size(),mx);
        q.insert(a[i]);
    }
    cout<<mx<<endl;
    
}
void main_init() {}
signed main(){
    AC();clapping();TLE;
    cout<<fixed<<setprecision(12);
    main_init();
//  while(cin>>n,n)
//  while(cin>>n>>m,n,m)
    int t;cin>>t;while(t -- )
    solve();
//    {solve(); }
    return 0;
}
 
/*样例区
 
 
*/
 
//------------------------------------------------------------

E1:(easy版) lcm的性质:必定是最大的数的倍数数据范围一眼做法 

题意:多组询问。lcm(i,j,k) >= i + j + k,问l 到 r 之间有多少满足条件的。l ,r <= 2e5。t <= 10

有一个性质:l 和 r 都是 1e5级别的,搜索三元组爆搜 要 n ^3,稍微优化:n^2 很难到 nlogn或者 n根号n。这里一眼可以确定要筛出某些数,在筛出来的数里搜了。

[l,r] 区间内三元组的数目是 组合数Cn3,就等于 len * (len - 1) * (len - 2) / 6

对于lcm(i,j,k) >= i + j + k,并不好直接判断,将大于等于号改成小于号:lcm(i,j,k) < i + j + k 。然后从最共的三元组数量找出满足条件的三元组数量即可

假设i,j,k中最大的数是 k ,那 lcm = 2 * k 或者 k 才满足条件 :比i + j + k 小。如果是 3k 的话 肯定要比 i + j + k 大

如果 lcm == k 。那肯定满足条件,三元组总数 - 1

如果 lcm == 2 * k 。那肯定是 k % i != 0 && k % j != 0。如果 满足 2 * k < i + j + k 也满足条件,三元组总数 - 1

只要枚举 所有 的2 * k ,并且找出它的因子 i ,j ,剪枝即可

ps:

1.lcm == 2 * k,如果 第二大的数 比 最大的数 的一半还小,那肯定不满足条件,可以减少对第一个数的搜索

2.找出每个数的因子是 o(n根号n)

 

//-------------------------代码----------------------------

//#define int ll
const int N = 4e5+10;
int n,m;
V<int> g[N];
void solve()
{
//    cin>>n>>m;
    int l,r;cin>>l>>r;
    int len = r - l + 1;;
    ll res = 1ll * len * (len - 1) * (len - 2) / 6;
    for(int i = l + 2;i<=r;i++) {
        V<int> v;
        for(auto x:g[2*i]) {
            if(x < l) continue;
            if(i % x && x * 2 <= i) continue;//如果不是 i 的因子,说明它是 2 * i 的因子 ,要满足 lcm(i,j,k) < i + j + k 那它的大小至少要是 i 的一半, 
            if(x >= i) break;
            for(auto y : g[2*i]) {
                if(y < l) continue;
                if(y >= x) break;
                if(i % x || i % y ) res -= 2 * i < x + y + i;//如果lcm = 2 * k,就要判断 
                else res -- ; //lcm = k,直接减 
            }
        }
    }
}
void main_init() {
    fo(i,1,200000) {
        for(int j = i;j<=400000;j+=i) {
            g[j].pb(i);
        }
    }
}
signed main(){
    AC();clapping();TLE;
    cout<<fixed<<setprecision(12);
    main_init();
//  while(cin>>n,n)
//  while(cin>>n>>m,n,m)
    int t;cin>>t;while(t -- )
    solve();
//    {solve(); }
    return 0;
}

/*样例区


*/

//------------------------------------------------------------

E2:hard版(t <= 1e5)树状数组+离线算法

我们把所有的循环 l 和 r 以及它是第几个询问,装进结构体

枚举[1,i] 以 r 为关键词,所有的 l 都是已经被计算过的

当枚举到当前询问的 r 的时候,l 就是一个特征值,不同的l 答案不一样

所以我们把所有的 i j k 的权值放入到最小的数 i 里,

ans[id] -= sum - query( l - 1)

//-------------------------代码----------------------------

#define int ll
const int N = 4e5+10;
int n,m;

V<int> v[N];
V<pii> q[N];
int tr[N];
void add(int x,int v) {
    for(int i = x;i<N;i+=lowbit(i)) tr[i] += v;
}
int ans[N];
ll qq(int x) {
    ll res = 0;for(int i = x;i;i-=lowbit(i)) res += tr[i];return res;
}

void solve()
{
//    cin>>n>>m;
    int t;cin>>t;fo(i,1,t) {
        int l,r;cin>>l>>r;
        q[r].pb({l,i});int len = r - l + 1;
        ans[i] = len * (len - 1) * (len - 2) / 6 ;
    }
    
    int sum = 0;
    for(int i = 1;i<=200000;i++) {
        for(auto x:v[i * 2]) {
            if(x >= i) break;
            if((i % x) && x * 2 <= i) continue;
            for(int y:v[i * 2]) {
                if(y >= x) break;
                if(i % x || i % y) {
                    if(x + y + i > 2 * i) {
                        sum ++ ;
                        add(y,1);
                    }
                } else {
                    sum ++ ;add(y,1);
                }
            }
        }
        for(auto it : q[i]) {
            int l = it.first,id = it.second;
            ans[id] -= sum - qq(l-1);
        }
    }
    fo(i,1,t) {
        cout<<ans[i]<<'\n';
    }
}
void main_init() {
    for(int i = 1;i<=2e5;i++) {
        for(int j = i * 2;j<=4e5;j+= i) {
            v[j].pb(i);
        }
    }
}
signed main(){
    AC();clapping();TLE;
    cout<<fixed<<setprecision(12);
    main_init();
//  while(cin>>n,n)
//  while(cin>>n>>m,n,m)
//    int t;cin>>t;while(t -- )
    solve();
//    {solve(); }
    return 0;
}

/*样例区


*/

//------------------------------------------------------------

 

标签:lcm,int,Codeforces,len,cin,while,solve,Div,813
来源: https://www.cnblogs.com/er007/p/16629714.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有