CSP-J第四套模拟题补题报告——————————————————————S12679

CSP-J第四套模拟题补题报告——————————————————————S12679
分数报告:
T1,T2 AC,T3,T4 20分,赛后AK。
赛中概况:
T1,T2很快做完,T3,T4骗分。
题目解析:
时间限制:1秒        内存限制:256M
1.1 问题描述
现在科学家在培养 A,B,C 三种微生物,这三种微生物每一秒都会繁殖出新的微生物,具体规则为:
A 类微生物每一秒会繁殖出 1 个 A 类微生物,1 个 B 类微生物,1 个 C 类微生物。
B 类微生物每一秒会繁殖出 2 个 A 类微生物,2 个 C 类微生物。
C 类微生物每一秒会繁殖出 1 个 A 类微生物,1 个 B 类微生物。
假设所有的微生物都不会死亡,一开始培养皿中有 A,B,C  三种微生物各 1 个,现在问你 nn 秒后 A,B,C 三种微生物分别有奇数个还是偶数个。
1.2 输入格式
从文件 three.in 中读取数据。
一行一个整数 n。
1.3 输出格式
输出到文件 three.out 中。
输出总共三行:
第一行:若 n 秒后 A 类微生物有奇数个,输出 odd,否则输出 even。
第二行:若 n 秒后 B 类微生物有奇数个,输出 odd,否则输出 even。
第三行:若 n 秒后 C 类微生物有奇数个,输出 odd,否则输出 even。
1.4 输入样例1
3
1.5 输出样例1
odd
odd
odd
1.6 输入样例2
4
1.7 输出样例2
odd
odd
even
1.8 输入样例3
233
1.9 输出样例3
even
even
odd
1.10 数据描述
总共  20  个测试点:
对于测试点  1∼4:1≤n≤3。
对于测试点  5∼8: 1≤n≤100。
对于测试点  9∼20: 1≤n≤10​6​​。
数据才1e6,直接暴力
上代码:
#include<bits/stdc++.h>
using namespace std;
int main(){
    freopen("three.in","r",stdin);
    freopen("three.out","w",stdout);
    long long n,a=1,b=1,c=1;
    scanf("%lld",&n);
    for(int i=1;i<=n;i++){
        long long a1=0,a2=0,a3=0;
        a1=a+c+2*b;
        a2=a+c;
        a3=a+2*b;
        a+=a1;
        b+=a2;
        c+=a3;
        a%=2;
        b%=2;
        c%=2;
    }
    if(a%2==1)printf("odd\n");
    else printf("even\n");
    if(b%2==1)printf("odd\n");
    else printf("even\n");
    if(c%2==1)printf("odd");
    else printf("even");
    fclose(stdin);
    fclose(stdout);
    return 0;
}


合体(fit)
时间限制:1秒        内存限制:256M
2.1 问题描述
现在有 n 个大小范围在 1∼m 中的整数 a​1​​∼a​n​​,并且你获得了一项魔法能力。
施加一次魔法能力后,可以将两个相同的数字合并成一个数字,并且这个数字为原来的数字 +1,例如:
有 2,2 这两个数字,施加一次魔法能力后可以将这两个数字合并成一个数字 3。
现在有 q 次询问,每次询问给你一个整数 x,你可以施加任意次数魔法能力,问你这 n 个整数最多能得到多少个整数 x?
2.2 输入格式
从文件 fit.in 中读取数据。
第一行两个整数 n,m。
第二行 n 个整数 a​1​​∼a​n​​。
第三行一个整数 q。
接下来 q 行,每行一个整数 x。
2.3 输出格式
输出到文件 fit.out 中。
输出 q 行,对于每个询问,输出对应的答案。
2.4 输入样例
10 4
1 1 1 2 1 3 4 1 2 3
5
1
2
3
4
4
2.5 输出样例
5
4
4
3
3
2.6 数据描述
总共 20 个测试点:
对于测试点 1∼4:1≤n≤10,1≤m≤10,1≤a​i​​≤m,1≤q≤10,1≤x≤m。
对于测试点 5∼6:1≤n≤10​6​​,m=1,a​i​​=1,q=1,x=1。
对于测试点 7∼8:1≤n≤10​6​​,m=5,1≤a​i​​≤m,1≤x≤m。
对于测试点 9∼20:1≤n≤10​6​​,1≤m≤10​6​​,1≤a​i​​≤m,1≤x≤m。

类似于2048游戏,m不大,可以直接打表。(不要不写scanf,printf)
代码:
#include<bits/stdc++.h>
using namespace std;
long long n,m,a[1000010],b[1000010]={0},q,c[1000001]={0};
int main(){
    freopen("fit.in","r",stdin);
    freopen("fit.out","w",stdout);
    scanf("%lld%lld",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%lld",&a[i]);
        b[a[i]]++;
    }
    for(int i=1;i<=m;i++){
        c[i]=b[i];
        b[i+1]+=b[i]/2;
    }
    scanf("%lld",&q);
    while(q--){
        long long x;
        scanf("%lld",&x);
        printf("%lld\n",c[x]);
    }
    fclose(stdin);
    fclose(stdout);
    return 0;
}

矩阵(matrix)
时间限制:2秒        内存限制:256M
3.1 问题描述
现在给你一个 n 行 m 列的矩阵,矩阵上每个格子有一个整数,其中第 i 行第 j 列对应的格子上的整数为 g​i,j​​。
现在定义该矩阵的一个子矩阵的快乐值为该子矩阵上的所有数字的异或和。
一组数字 a​1​​,a​2​​,...,a​n​​ 的异或和为 a​1​​ xor a​2​​ xor ... xor a​n​​。(其中 xor 表示按位异或运算)
现在问你,该矩阵的所有子矩阵的快乐值之和为多少?
3.2 输入格式
从文件 matrix.in 中读取数据。
第一行两个整数 n,m。
接下来n 行,每行m 个整数,表示该矩阵。
3.3 输出格式
输出到文件 matrix.out 中。
一行一个整数,表示答案。
3.4 输入样例
5 4
3 2 1 2
3 3 5 5
8 7 3 6
1 1 1 1
2 3 9 9
3.5 输出样例
822
3.6 数据描述
总共 20 个测试点:
对于测试点 1∼4:1≤n,m≤10,0≤g​i,j​​<2​10​​。
对于测试点 5∼6:1≤n,m≤300,g​i,j​​=1。
对于测试点 7∼12:1≤n,m≤300,0≤g​i,j​​≤1。
对于测试点 13∼20:1≤n,m≤300,0≤g​i,j​​<2​10​​。
用前缀和的思路,再转成高精度。

代码:
#include<bits/stdc++.h>
using namespace std;
long long n,m,a[310][310],cnt=0,x[310],xo[310];
int main(){
    freopen("matrix.in","r",stdin);
    freopen("matrix.out","w",stdout);
    scanf("%lld%lld",&n,&m);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            scanf("%lld",&a[i][j]);
        }
    }
    for(int i=1;i<=n;i++){
        memset(x,0,sizeof(x));
        for(int j=i;j<=n;j++){
            for(int k=1;k<=m;k++){
                x[k]^=a[j][k];
                xo[k]=xo[k-1]^x[k];
            } 
            for(int l=0;l<10;l++){
                long long cnt0=1,cnt1=0;
                for(int r=1;r<=m;r++){
                    if(xo[r]&(1<<l)){
                        cnt+=cnt0*(1<<l);
                        cnt1++;
                    }else{
                        cnt+=cnt1*(1<<l);
                        cnt0++;
                    }
                }
            }
        }
    }
    printf("%lld\n",cnt);
    fclose(stdin);
    fclose(stdout);
    return 0;
}

数对(pair)
时间限制:2秒        内存限制:256M
4.1 问题描述
给你一个长度为 n 的数列 a​1​​,a​2​​,...,a​n​​。
再给你一个长度为 m 的数列 b​1​​,b​2​​,...,b​m​​。
现在再再再给你一个正整数 p,让你生成一个长度为 n×m 的数列 c​1​​,c​2​​,...,c​n×m​​。
其中满足 c​(i−1)×m+j​​=(a​i​​+b​j​​) mod p。
现在问你数列 c 中有多少个数对 (i,j) 满足 i<j 且c​i​​>c​j​​?
4.2 输入格式
从文件 pair.in 中读取数据。
第一行两个整数 n,m,p。
第二行 n 个整数,表示 a​1​​∼a​n​​。
第三行 m 个整数,表示 b​1​​∼b​m​​。
4.3 输出格式
输出到文件 pair.out 中。
一行一个整数,表示答案。
4.4 输入样例
6 7 10
1 1 4 5 1 4
1 9 1 9 8 1 0
4.5 输出样例
294
4.6 数据描述
总共 20 个测试点:
对于测试点 1∼4:1≤n,m≤100,1≤p≤10,0≤a​i​​,b​i​​<p。
对于测试点 5∼6:1≤n,m≤1000,1≤p≤10,0≤a​i​​,b​i​​<p。
对于测试点 7∼8:1≤n,m≤1000000,p=2,0≤a​i​​,b​i​​<p。
对于测试点 9∼20:1≤n,m≤1000000,1≤p≤10,0≤a​i​​,b​i​​<p。
代码:#include<bits/stdc++.h>
#define ll long long
using namespace std;
bool flag=0;
const int N=1e6+5,M=1e6+5;
int n,m,p,a[M],b[M];
ll num[10],numb[M],nixu[10];
ll ans[200],cnt=0;
void jia(ll k){
    ans[0]+=k;
    int pos=0;
    while(1){
        if(ans[pos]>=1000000){
            ans[pos+1]+=ans[pos]/1000000;
            ans[pos]%=1000000;
            if(++pos>cnt)cnt++;
        }else break;
    }
}
int main(){
    cin>>n>>m>>p;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        if(a[i]!=0)flag=1;
    }
    for(int i=1;i<=m;i++){
        cin>>b[i];
        if(b[i]!=0)flag=1;
        numb[b[i]]++;
    }
    for(int j=0;j<p;j++){
        memset(num,0,sizeof(num));
        for(int i=1;i<=m;i++){
            for(int k=b[i]+1;k<p;k++)nixu[j]+=num[k];
            num[b[i]]++;
            b[i]=(b[i]+1)%p;
        }
    }
    memset(num,0,sizeof(num));
    for(int i=1;i<=n;i++){
        jia(nixu[a[i]]);
        for(int j=0;j<p;j++){
            int x=(j+a[i])%p;
            for(int k=x+1;k<p;k++){
                ll x=1ll*numb[j]*num[k];
                jia(x);
            }
        }
        for(int j=0;j<p;j++)num[(j+a[i])%p]+=numb[j];
    }
    if(!flag)cout<<0;
    else{
        cout<<ans[cnt];
        for(int i=cnt-1;i>=0;i--)printf("%06lld",ans[i]);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值