iwtgm-8

题目链接

A.

模拟,
先遍历一遍,出现0,则i+x和i-x存在则必是0
再遍历一遍,出现1,判i+x和i-x位上若已经是1或还没被赋值则满足题意,否则失败退出
输出是当前位是1,则输出1,否则输出0.因为1的限制范围明确,其余都填0

void solve(){
    string s;cin>>s;
    int x;cin>>x;
    char c[N];
    int len=s.size();
    for(int i=0;i<len;i++)c[i]='#';
    for(int i=0;i<len;i++){
        if(s[i]=='0') {
            if (i + x < len)c[i + x] = '0';
            if (i - x >= 0)c[i - x] = '0';
        }
    }
    for(int i=0;i<len;i++){
        if(s[i]=='1'){
            if(i+x<len&&(c[i+x]=='#'||c[i+x]=='1')){
                c[i+x]='1';continue;
            }
            else if(i-x>=0&&(c[i-x]=='#'||c[i-x]=='1')){
                c[i-x]='1';continue;
            }else {
                cout << -1 << endl;return ;
            }
        }
    }
    for(int i=0;i<len;i++){
        if(c[i]=='#'){
            if(s[i+x]=='1'){
                c[i]='1';continue;
            }
            if(s[i-x]=='1'){
                c[i]='1';continue;
            }
            c[i]='0';
        }
    }
    for(int i=0;i<len;i++)cout<<c[i];
    cout<<endl;
}

B.

x每个数一定会加,直接答案+xn
想让d的贡献大,则设定i是头或尾,这样就是(n-1)
n/2d的贡献(因为一定会有i==j的情况)
想让d的贡献小,则设定i为中间的那个
奇数是(n/2)
(n/2+1)d的贡献(中间值的左右两边所以/22抵消)
偶数是((n/2)(n/2+1)-n/2)的贡献(减去i==j的情况)

n也要开long long,因为后面计算是n*n,猛wa五发

void solve(){
    ll n,m;cin>>n>>m;
    ll x,d;
    long double ans=0;
    for(ll i=0;i<m;i++){
        cin>>x>>d;
        ans+=x*n;
        if(d==0)continue;
        if(d>0){
            ans+=d*((n-1)*n/2);continue;
        }
        if(d<0){
            if(n&1){
                ll tmp=n/2;
                ans+=tmp*(tmp+1)*d;continue;
            }else{
                ll tmp=n/2,tp=tmp-1;
                ans+=tmp*(tmp+1)/2*d;
                ans+=tp*(tp+1)/2*d;
            }
        }
    }
    ans=ans*1.0/n;
    cout<<fixed<<setprecision(9)<<ans;
}

C.

数位dp,代码注释得很详细了

ll l,r;
ll a[25],f[25][25];//a是数位数组,f[][]第一维是数位,第二维根据题目定(这里是非0的个数)
ll dfs(int pos,bool limit,int sum){//数位,是否受限,据题意可变参数(这里是非0的个数)
    if(!pos)return 1;//超过了,这里是满足条件返回1(这个数非0位不超过3,算一个贡献)
    if(!limit&&f[pos][sum]!=-1)return f[pos][sum];//不受限且搜过了(记忆的是更普遍的不受限的情况)
    int up=limit?a[pos]:9;//受限就是数位上的值,不受限则可取1-9
    ll res=0;
    for(int i=0;i<=up;i++){//枚举
        if(i==0)res+=dfs(pos-1,limit&&i==up,sum);//这里据题意,这里是当前位是0,没有增加贡献
        else if(sum!=3)res+=dfs(pos-1,limit&&i==up,sum+1);//这里据题意,这里是当前位非0,增加一个贡献
    }
    if(!limit)f[pos][sum]=res;//记忆
    return res;
}
ll pre(ll x){
    int len=0;
    while(x>0){//记录每个数位上的值
        a[++len]=x%10;
        x/=10;
    }
    return dfs(len,true,0);//从最高位开始搜,最高位limit是0(有限制,不能任意取,且无前导0,最后一个参数根据题目具体定)
}
void solve(){
    memset(f,-1,sizeof(f));//f[][]数组初始化为-1
    cin>>l>>r;//边界
    ll ans=pre(r)-pre(l-1);
    cout<<ans<<endl;
}
posted @ 2023-11-02 13:23  WW爆米花  阅读(3)  评论(0编辑  收藏  举报