A

solution:

入门的二维动态规划,每个点只会影响其右方和下方的位置,遍历输出答案即可

std:

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int mod = 1e9+7;
string s[55];
int dp[55][55];
int main(){
    int n,m;
    cin>>n>>m;
    for(int i=0;i<n;i++){
        cin>>s[i];
    }
    dp[0][0] = 1;
    for(int i=0;i<n;i++){
        for(int j=0;j<m;j++){
            char c = s[i][j];
            if(c == 'R'){
                dp[i][j+1] += dp[i][j] ;
                dp[i][j+1] %= mod;
            }
            if(c == 'D'){
                dp[i+1][j] += dp[i][j];
                dp[i+1][j] %= mod;
            }
            if(c == 'B'){
                dp[i+1][j] += dp[i][j];
                dp[i][j+1] += dp[i][j];
                dp[i+1][j] %= mod;
                dp[i][j+1] %= mod;
            }
        }
    }
    cout<<dp[n-1][m-1]<<endl;
    return 0;
}

B

solution:

构造,和第一题要求相反,要求构造迷宫,考虑二进制,直接上图

左图是初始的矩阵,对角线是B,往下一行是R,其余全是D
右图是构造出n=13的矩阵 ,我们将13的二进制为1的位置的下标对应的位置的R都变成B即可

std:

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int mod = 1e9+7;
int a[55][55];
int main()
{
    ll k;
    cin>>k;
    k %= mod;
    cout<<"50 50"<<endl;
    for(int i=1;i<=40;i++){
        a[i][i] = 1;
        a[i][i+1] = 2;
        a[i+1][i] = 3;
        for(int j=i+2;j<=49;j++){
            a[j][i] = 2;
        }
    }
    for(int i=1;i<=50;i++){
        a[50][i] = 3;
    }
    for(int i=30;i>=1;i--)
    {
        int x = (1<<(i-1));
        if(k >= x){
            k -= x;
            a[i+1][i] = 1;
        }
        if(k == 0){
            break ;
        }
    }
    for(int i=1;i<=50;i++){
        for(int j=1;j<=50;j++){
            if(a[i][j] == 1){
                cout<<"B";
            }
            else if(a[i][j] == 2){
                cout<<"D";
            }
            else if(a[i][j] == 3){
                cout<<"R";
            }
            else{
                cout<<"R";
            }
        }
        cout<<endl;
    }
    return 0;
}

C

solution:

题目长,但是题简单,题目明确说明“无论是否发生数组越位或者非法访问,输入数据都要完整读入",所以不要中途break,按照题目写应该没什么问题

std:

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 1004;
int a[maxn][maxn];
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        memset(a,0,sizeof(a));
        ll n,m,x,y;
        int p;
        int flag = 0,val;
        cin>>n>>m>>p;
        ll maxx = n*m - 1;
        while(p--)
        {
            cin>>x>>y>>val;
            if(flag == 2){
                continue ;
            }
            ll pos =m*x + y;
            if(pos > maxx || pos < 0){
                flag = 2;
                continue ;
            }
            if(x < 0 || x >= n || y < 0 || y >= m){
                flag = 1;
                int xx = (int)pos/m;
                int yy = (int)pos%m;
                a[xx][yy] = val;
                continue ;
            }
            a[x][y] = val;
        }
        //cout<<"yes"<<flag<<endl;
        if(flag == 2){
            printf("Runtime error\n");
            continue ;
        }
        if(flag == 1){
            for(int i=0;i<n;i++){
                for(int j=0;j<m;j++){
                    if(j != 0)
                        printf(" ");
                    printf("%d",a[i][j]);
                }
                printf("\n");
            }
            printf("Undefined Behaviour\n");
            continue ;
        }
        if(flag == 0){
            for(int i=0;i<n;i++){
                for(int j=0;j<m;j++){
                    if(j != 0)
                        printf(" ");
                    printf("%d",a[i][j]);
                }
                printf("\n");
            }
            printf("Accepted\n");
            continue ;
        }
    }
    return 0;
}

D

solution:

按照题目意思写出来基本上就对了,记得先用牛客本地数据编译一遍

std:

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn = 200005;
map<int , int> mp;
int a[maxn];
int main()
{
    int sum = 0 ,n;
    scanf("%d",&n);
    memset(a, -1 ,sizeof(a));
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        if(a[i] != -1){
            sum++;
            mp[a[i]] = i;
        }
    }
    printf("The size of the tree is %d\n",sum);
    printf("Node %d is the root node of the tree\n",a[1]);
    for(int i=1;i<=sum;i++)
    {
        printf("The father of node %d is %d, the left child is %d, and the right child is %d\n",i , a[mp[i]/2] , a[mp[i]*2] , a[mp[i]*2 + 1]);
    }
    return 0;
}

E

solution:

这个题确实可以考虑笨一点的办法
考虑二进制对答案的贡献,假设[l1,r1]中二进制第k位0的个数位cntx0,1的个数位cnty0;同样的[l2,r2]中二进制第k位0的个数位cntx1,1的个数位cnty1,那么产生的贡献就是2^k×(cntx0×cnty1 + cntx1×cnty0),理解了这个式子,就可以有技巧的解决这一道题了,but如果想考虑少一点,用容斥的方法去做

std:

#include <bits/stdc++.h>
using namespace std;
#define ll long long
ll pow_mod(ll a,ll b,ll mod){
    ll ans = 1;
    a%=mod;
    while(b){
        if(b&1)
            ans = ans*a%mod;
        a = a*a%mod;
        b>>=1;
    }
    return ans;
}
const ll mod = 1e9 + 7;
ll z = 1;
ll get(ll n,ll k)//从1到n的第k位2进制有多少1
{
    ll cnt = 0;
    n++;
    cnt = n/(2ll<<k)*(z<<k);
    n %= (2ll<<k);
    if(n > (z<<k))
        cnt += (z<<k);
    else
        cnt += n;
    return cnt;
}
ll f(ll l ,ll r,ll k){
    return ((get(r,k) - get(l-1,k))%mod + mod)%mod;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        ll l1,l2,r1,r2,ans1 = 0,ans2 = 0;
        scanf("%lld%lld%lld%lld",&l1,&r1,&l2,&r2);
        ll len1 = (r1 - l1 + 1)%mod , len2 = (r2 - l2 + 1)%mod;
        ans1 = pow_mod(len1*len2%mod, mod - 2,mod);
        for(ll i=0;i<=62;i++){
            ll x = f(l1 , r1 , i);
            ll y = f(l2 , r2 , i);
            ans2 = (ans2 + (z<<i)%mod*x%mod*(len2 - y)%mod)%mod;
            ans2 = (ans2 + (z<<i)%mod*y%mod*(len1 - x)%mod)%mod;
        }
        ans1 = (ans1*ans2%mod + mod)%mod;
        printf("%lld\n",ans1);
    }
    return 0;
}

F

solution:

前缀和,考虑新出现的一个点对答案的贡献,就等于新出现的点再重新和前n-1个点连n-1条边,每次只需记录上一个点的位置,维护前缀和

std:

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const ll mod = 1e9+7;
const int maxn = 100005;
char s[maxn];
int main()
{
    int n;
    scanf("%d",&n);
    scanf("%s",s);
    int pos = 0;
    for(int i=0;i<n;i++){
        if(s[i] == '1'){
            pos = i;
            break ;
        }
    }
    ll ans = 0;
    ll len = 0;
    int pre = pos, k = 1;
    for(int i = pos+1;i<n;i++)
    {
        if(s[i] == '1'){
            len = len + k*(i - pre);
            ans = ans + len;
            len %= mod;
            ans %= mod;
            pre = i;
            k++;
        }
        //cout<<ans<<endl;
    }
    cout<<ans;
    return 0;
}

G

solution:

待补

std:

H

solution:

先处理出来1e5内的所有质数,枚举1e5,记录每一个数的因子非质数的个数,O(1)输出答案即可

std:

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxx = 100010;
int a[maxx];
bool pri[maxx];
int cnt1 = 0,cnt2 = 0;
void prime()
{
    for(int i=2;i<maxx;i++)
        pri[i] = 1;
    for(int i=2;i<maxx;i++)
    {
        if(pri[i])
            a[cnt1++] = i;
        for(int j=0;(j<cnt1 && i*a[j]<maxx);j++)
        {
            pri[i*a[j]] = 0;
            if(i%a[j] == 0)
                break;
        }
    }
}
int ans[maxx];
int n,m;
map<int ,int > mp;
void solve()
{
    for(int i=3;i<=n;i++){
        if(pri[i]){
            continue ;
        }else{
            ans[i]++;
        }
        for(int j=2;j*j<=i;j++){
            if(i%j == 0){
                int x = i/j;
                int y = j;
                if(x != y){
                    if(!pri[x]){
                        ans[i]++;
                    }
                    if(!pri[y]){
                        ans[i]++;
                    }
                }else{
                    if(!pri[x]){
                        ans[i]++;
                    }
                }
            }
        }
    }
    for(int i=1;i<=n;i++){
        mp[ans[i]]++;
    }
}
int main()
{
    cin>>n>>m;
    prime();
    solve();
    int x;
    while(m--){
        scanf("%d",&x);
        printf("%d\n",mp[x]);
    }
    return 0;
}

I

solution:

递推,dp[i][j][k]表示在第i种情况下n层汉诺塔产生第k中操作的次数

std:

#include <bits/stdc++.h>
using namespace std;
#define ll long long
ll dp[7][70][7];// 第i种情况的j层汉诺塔产生第k种操作的次数
int main()
{
    int n;
    cin>>n;
    for(int i=0;i<6;i++)
        dp[i][1][i] = 1;
    for(int i=2;i<=n;i++)
    {
        for(int j=0;j<6;j++)
        {
            dp[j][i][j]++;
        }
        for(int j=0;j<6;j++) dp[0][i][j] += dp[1][i-1][j] + dp[5][i-1][j];
        for(int j=0;j<6;j++) dp[1][i][j] += dp[0][i-1][j] + dp[3][i-1][j];
        for(int j=0;j<6;j++) dp[2][i][j] += dp[3][i-1][j] + dp[4][i-1][j];
        for(int j=0;j<6;j++) dp[3][i][j] += dp[2][i-1][j] + dp[1][i-1][j];
        for(int j=0;j<6;j++) dp[4][i][j] += dp[5][i-1][j] + dp[2][i-1][j];
        for(int j=0;j<6;j++) dp[5][i][j] += dp[4][i-1][j] + dp[0][i-1][j];

    }
    printf("A->B:%lld\n", dp[1][n][0]);
    printf("A->C:%lld\n", dp[1][n][1]);
    printf("B->A:%lld\n", dp[1][n][2]);
    printf("B->C:%lld\n", dp[1][n][3]);
    printf("C->A:%lld\n", dp[1][n][4]);
    printf("C->B:%lld\n", dp[1][n][5]);
    printf("SUM:%lld\n", 1ll*(1ll*1<<1ll*n) - 1);

    return 0;
}

J

solution:no solution,菜