20南京站补题(EF)+cf数学

Posted 钟钟终

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了20南京站补题(EF)+cf数学相关的知识,希望对你有一定的参考价值。

H. Gambling

自己的代码属实丑陋,虽然该注意到的点都想到了,但就是打不对。可能还是思路不够清晰,代码能力不过关。
思路:
1.刚开始的钱是1元。因此对于一个数来说,后面跟着的数在数量上不能超过该数字的有效数量(抵消的时候记录最大值)。
2.主要发生抵消后的数字大于等于1,那么就记录更新。过程中记录最大值和左右端点。
代码:

#include <bits/stdc++.h>
#define int long long
#define ios cin.tie(0),cout.tie(0),ios::sync_with_stdio(0);
#define endl '\\n'
#define ULL unsigned long long
using namespace std;
const double eps=1e-8;
const int mod=998244353;
const int N=1e6+5;
const int P=131;
int n,a[N];
unordered_map<int,pair<int,int>>mp;
unordered_map<int,int>val;
void solve()

    mp.clear();
    val.clear();
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    int mx=1,ans=a[1],l=1,r=1;
    for(int i=1;i<=n;i++)
    
        if(mp.count(a[i]))
        
            int tmp=val[a[i]];
            tmp=tmp-(i-mp[a[i]].second-1)+1;
            //cout<<a[i]<<" "<<val[a[i]]<<" "<<tmp<<endl;
            if(tmp<=0)
            
                mp[a[i]]=i,i;val[a[i]]=1;
            
            else
            
                val[a[i]]=tmp;
                mp[a[i]].second=i;
            
            if(mx<val[a[i]])
                mx=val[a[i]],ans=a[i],l=mp[a[i]].first,r=mp[a[i]].second;
        
        else
        
            mp[a[i]]=i,i;val[a[i]]=1;
        
    
    cout<<ans<<" "<<l<<" "<<r<<endl;

signed main()

    ios;
    int T;cin>>T;
    while(T--)
        solve();
    return 0;

//    int ans=0,l=0,r=0,mx=0;
//    for(int i=1;i<=n;i++)
//    
//        cin>>a[i];
//        if(!mp[a[i]].size())
//        
//            mp[a[i]].push_back(i),val[a[i]]=1,mm[a[i]]=i,i;
//            if(mx<val[a[i]])
//                mx=val[a[i]],ans=a[i],l=mm[a[i]].first,r=mm[a[i]].second;
//            continue;
//        
//        if(i-mp[a[i]].back()-1>=mp[a[i]].size())
//        
//            mp[a[i]].clear();mp[a[i]].push_back(i);
//            val[a[i]]=1;mm[a[i]]=i,i;
//        
//        int p=mp[a[i]].back();
//        mp[a[i]].push_back(i);
//        if(mp[a[i]].size()-(i-p-1)>val[a[i]])
//        
//            val[a[i]]=mp[a[i]].size()-(i-p-1);
//            mm[a[i]]=mp[a[i]].front(),i;
//        
//        if(mx<val[a[i]])
//            mx=val[a[i]],ans=a[i],l=mm[a[i]].first,r=mm[a[i]].second;
//    
//    int g,mx=0;
//    for(auto x:mp)
//    
//        int tmp=0;
//        for(int i=0;i<x.second.size();i++) cout<<mp[x.first][i]<<" ";
//        cout<<endl;
//        for(int i=x.second.size()-1;i>=1;i--)
//        
//            tmp+=mp[x.first][i]-mp[x.first][i-1]-1;
//        
//        int p=mp[x.first].size();
//        int q=mp[x.first].back()-mp[x.first].front()+1-p;
//        //cout<<p<<" "<<q<<endl;
//        p=p-q;
//        //cout<<p<<endl;
//        if(p>mx)
//        
//            mx=p;g=x.first;
//        
//    

F .Fireworks

学到的新技巧,三分板子。用于处理凹凸函数的极值问题,感觉跟模拟退火很像。
思路:
1.对于一批做好的火柴,都失败的概率为(1-p)k ,则成功的概率为1-(1-p)k
2.则1/1-(1-p)k 是期望的次数,每次的时间为n*k+m
3.得出公式:n * k+m/(1-(1-p)k
4.判断函数为凹凸函数,两次求到后结果为常数.(对于一定为整数的分母,可选择性不看,分子进行二次求导可全约掉)
4.处理方法有三分和模拟退火。

#include <bits/stdc++.h>
#define int long long
#define ios cin.tie(0),cout.tie(0),ios::sync_with_stdio(0);
#define endl '\\n'
#define ULL unsigned long long
using namespace std;
const double eps=1e-8;
const double dinf=1e18;
const int mod=998244353;
const int P=131;
const int N=1e6+5;

double n,m,p,ans=dinf;

double fun(int x)

    return (1.0*x*n+m)/(1-pow(1-p,x));


void solve()

    cin>>n>>m>>p;
    p*=1e-4;
    int l=0,r=1e9;
    while(l+5<=r)
    
        int m1=(l+r)>>1;
        int m2=(m1+r)>>1;
        if(fun(m1)>fun(m2)) l=m1;
        else r=m2;
    
    ans=fun(l);
    for(int i=l+1;i<=r;i++)
        ans=min(ans,fun(i));
    cout<<fixed<<setprecision(12)<<ans<<endl;

signed main()

    ios;
    int T;cin>>T;
    while(T--)
        solve();
    return 0;



被卡掉的模拟退火做法:

#include <bits/stdc++.h>
#define int long long
#define ios cin.tie(0),cout.tie(0),ios::sync_with_stdio(0);
#define endl '\\n'
#define ULL unsigned long long
#define down 0.996
using namespace std;
const double eps=1e-8;
const double dinf=1e18;
const int mod=998244353;
const int P=131;
const int N=1e6+5;

double n,m,p,answ;
int ansx;

double fun(int x)

    return (1.0*x*n+m)/(1-pow(1-p,x));

void sa()

    double t=2000;
    while(t>1e-12)
    
        int ax=ansx+(rand()*2-RAND_MAX)*t; // [-32767,+32767]
        if(ax<=0) continue;
        double aw=fun(ax);    //随机跳值的x位置的y值
        double ad=aw-answ;
        if(ad<0)    //新值小于原值,接受
            ansx=ax,answ=aw;
        else if(exp(-ad/t)*RAND_MAX>rand())        //新值大于原值,根据概率接受
        
            ansx=ax;
        
        t*=down;
    

void solve()

    cin>>n>>m>>p;
    p*=1e-4;
    ansx=n+m,answ=fun(ansx);
    //cout<<ansx<<" "<<answ<<endl;
    sa();
    //cout<<ansx<<endl;
    cout<<fixed<<setprecision(12)<<fun(ansx)<<endl;

signed main()

    ios;
    int T;cin>>T;
    while(T--)
        solve();
    return 0;

E. Evil Coordinate

想了一个100多行的假代码后,终于想到一个全排列的好方法。
复杂度:O(24*N)
统计各个方向出现的次数,再对LRUD全排列,构造出不同路径,选择一个满足的。

#include <bits/stdc++.h>
using namespace std;
#define int long long
#define endl '\\n'
const int N = 1e6+100;
int t,mx,my,n;
unordered_map<char,int>mp;
signed main()

    //cin.tie(0);ios::sync_with_stdio(0);cout.tie(0);
    cin>>t;
    while(t--)
    
        char s[4]='D','L','R','U';
        sort(s,s+4);
        mp.clear();
        cin>>mx>>my;
        string ss;cin>>ss;
        if(mx==0&&my==0)
        
            cout<<"Impossible"<<endl;continue;
        
        n=ss.length();
        for(int i=0;i<n;i++) mp[ss[i]]++;
        int flag=1;
        do
            string ans="";
            int x=0,y=0,g=0;
            for(int i=0;i<4;i++)
            
                if(s[i]=='D')
                
                    for(int j=mp['D'];j>=1;j--)
                    
                        y--;
                        if(x==mx&&y==my)
                        
                            g=1;break;
                        
                    
                    for(int j=1;j<=mp['D'];j++) ans+='D';
                
                else if(s[i]=='L')
                
                    for(int j=mp['L'];j>=1;j--)
                    
                        x--;
                        if(x==mx&&y==my)
                        
                            g=1;break;
                        
                    
                    for(int j=1;j<=mp['L'];j++) ans+='L';
                
                else if(s[i]=='R')
                
                    for(int j=mp['R'];j>=1;j--)
                    
                        x++;
                        if(x==mx&&y==my)
                        
                            g=1;break;
                        
                    
                    for(int j=1;j<=mp['R'];j++) ans+='R';
                
                else if(s[i]=='U')
                
                    for(int j=mp['U'];j>=1;j--)
                    
                        y++;
                        if(x==mx&&y==my)
                        
                            g=1;break;
                        
                    
                    for(int j=1;j<=mp['U'];j++) ans+='U';
                
            
            if(g==1) continue;
            flag=0;
            cout<<ans<<endl;
            break;
        while(next_permutation(s,s+4));
        if(flag)
            cout<<"Impossible"<<endl;
    
    return 0;


以上是关于20南京站补题(EF)+cf数学的主要内容,如果未能解决你的问题,请参考以下文章

Educational Codeforces Round 24 CF 818 A-G 补题

{CF812}

偷懒的思维 极端条件--极值

CF补题

cf 595 补题

4.30-5.1cf补题