BNUZit节2022网络赛

浅浅被c#老师强迫参赛吧,然后浅浅解析一下题木吧

A题:我是先记录最大值,然后用哈希表存储再最后判断是否最大输出的emm

#include 
#include
#include
#include 
#include
#include
using namespace std;

int arr[20000];
vector ans;
int main()
{
	
	string s;
	cin >> s;
	
	int n = s.size();
	int maxn = 0;
	for (int i = 0; i < n; i++) {
		unordered_set st;
		string e; int  cnt = 0;
		for (int j = i; j < n; j++) {
			if (st.count(s[j]) != 0)
				break;
			e += s[j];
			st.insert(s[j]);
			cnt++;
		}
		st.clear();
		ans.push_back(e);
		maxn = max(maxn,cnt);
	}
	for (auto& ch : ans)
		if(ch.size()==maxn)
		cout << ch << endl;
	return 0;
}

B:无聊题跳0.0

C:这边表示题目太长懒直接不做

D:最大化最小值吧 二分查找

#include 
#include 
using namespace std;
const int N = 1e3 + 5;

int n, m, ans = 0;
int len[N];

bool f(int mid) {
    int index = len[1], ans = 1;//ans就是看看能不能放完全部单词
    for (int i = 2; i <= n; i++) {
        if (len[i] - index >= mid) {//比较前后两个位置间隔是否符合现在的间隔所以要用数存在上一个
            index = len[i];
            ans++;
        }
    }
    return ans >= m;
}

int main() {
    int l = 0, r = 0;
    cin >> n >> m;
    len[0] = 0;
    for (int i = 1; i <= n; i++) {//记录最大,因为下面二分要缩小距离了
        cin >> len[i];
        r = max(len[i], r);
    }
    sort(len + 1, len + n + 1);//二分查找常规排序
    while (l < r) {
        int mid = (r + l + 1) >> 1;
        if (f(mid)) l = mid;//这个表示这个间隔能放完全部单词,但不一定是最长距离所以继续扩大
        else r = mid - 1;//表示这个间隔放不完全部单词,间隔太长缩小
    }
    cout << l << endl;
}

E:数学题,无感跳过0.0

F:这个很常规的题,但是那时候我以为tm我写错了ac不了,后面套了快速幂才过,我只能说狗

我是用了树状数组+差分+快速幂的,别问为什么不用线段树,线段树很长诶

#include
#include
#include
#include
using namespace std;
const int maxn = 100010;
typedef long long  LL;
LL a[maxn], d[maxn], di[maxn], sum[maxn], n, m;
LL cb[100001];
long long quick(long long a, long long b, long long mod) {
    long long ans = 1;
    a %= mod;
    while (b) {
        if (b & 1) {
            ans = (ans * a) % mod;

        }
        a = (a * a) % mod;
        b >>= 1;
    }
    return ans;
}
int lowbit(int x) {
    return x & (-x);
}
void Add(LL a[], LL x, LL d)
{
    while (x <= n)
    {
        a[x] += d;
        x += lowbit(x);
    }
}
LL Sum(LL a[], LL x)
{
    LL sum = 0;
    while (x > 0)
    {
        sum += a[x];
        x -= lowbit(x);
    }
    return sum;
}
int main() {
    while (cin >> n >> m) {
        memset(a, 0, sizeof(a));
        memset(d, 0, sizeof(d));
        memset(di, 0, sizeof(di));
        memset(sum, 0, sizeof(sum));
        for (int i = 1; i <= n; ++i)
            cin >> a[i];
        for (int i = 1; i <= n; ++i)
            sum[i] = sum[i - 1] + a[i];
        while (m--)
        {
            LL k, s, t, a, b;
            cin >> k;
            if (k == 2) {
                cin >> s >> t >> a >> b;   
                LL val;
                val = quick(a,b,442333);
                Add(d, s, val);
                Add(d, t + 1, -val);
                Add(di, s, s * val);
                Add(di, t + 1, -val * (t + 1));

            }
            else {
                cin >> s >> t;
                LL sum_a = sum[t] + (t + 1) * Sum(d, t) - Sum(di, t);
                LL sum_b = sum[s - 1] + s * Sum(d, s - 1) - Sum(di, s - 1);
                cout << (sum_a - sum_b) << endl;
            }
        }

    }
    return 0;
}

 G题:一开始以为是tm最短路,然后想了想n给太小了估计是状压emmm

#include 
#include 
using namespace std;
const int N = 21, M = 1 << N;
int n;
int f[N][M];
int a[N][N];
int cnt[M];
int ans = 0x3f3f3f;
int main()
{
    cin >> n;
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n; j++)
        {
            cin >> a[i][j];
        }
    memset(f, 0x3f3f3f, sizeof(f));
    f[0][1] = 0;//表示从起点出发,现在这个点的集合有一个了就是0节点[i]表示当前在的节点 【j】是集合
    for (int k = 0; k < (1 << n); k++)//枚举每一个状态 就比如  000 001 010 100 101 110 111emmm然后 010 表示访问过了第2个节点
        for (int i = 0; i < n; i++)//节点
        {
            if (k >> i & 1)//表示在节点里面  就是k取第i位看看是不是1 是就表示访问过
                for (int j = 0; j < n; j++)
                {
                    if (k >> j & 1 && a[j][i])//表示j到i点之间有路,并且j在集合里面
                        f[i][k] = min(f[i][k], f[j][k - (1 << i)] + a[i][j]);//表示把这个集合里面的这个i点去掉,已经走到了i点不需要他了
                }
        }
    int ans = 0x3f3f3f;
    for (int i = 0; i < n; i++) {
        ans = min(ans, f[n-1][(1<

H:常规动态规划,不说;

#include
#include
#include
#include
using namespace std;
const int maxn = 51;
long long dp[maxn];
int main() {
    int n;
    while (cin >> n) 
    {
        dp[1] = 1, dp[2] = 2;
    for (int i = 3; i <= maxn; i++) 
    {
        dp[i] = dp[i - 1] + dp[i - 2];
    }
        cout << dp[n] << endl;
    }
    return 0;
}

I:也是常规动态规划注意初始化边界就行

#include
#include
#include
#include
using namespace std;
int mp[101][101];
int dp[101][101];
int main()
{
    memset(mp, 0, sizeof(mp));
    memset(dp, 0, sizeof(dp));
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= i; j++)
        {
            cin >> mp[i][j];
        }
    }
    for (int i = 1; i <= n; i++)
    {
        for (int j = 1; j <= i; j++)
        {
            dp[i][j]= mp[i][j];
        }
    }
    for (int i = 2; i <= n; i++)
    {
        for (int j = 1; j <= i; j++)
        {
            if (j == 1)dp[i][j] = dp[i - 1][j] + mp[i][j];
            else if (j == i)dp[i][j] = dp[i - 1][j - 1] + mp[i][j];
            else
            {
                dp[i][j] = dp[i - 1][j - 1] + mp[i][j];
                dp[i][j] = max(dp[i][j], dp[i - 1][j] + mp[i][j]);
            }
        }
    }
    int ans = 0;
    for (int i = 1; i <= n; i++)
    {
        ans = max(ans, dp[n][i]);
    }
    cout << ans<

J:求最短路,因为是求任意两点间的距离所以用floy算法;让后记得建双向边就行了

#include
#include
#include
#include
#include
#include
#define ll long long
#define ull unsigned long long
#define INF 0x3f3f3f3f
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef  pair PII;
const int N = 10000;
int n, m, k;
int dp[N][N];
void floyd()
{
    for (int k = 1; k <= n; k++)
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= n; j++)
                dp[i][j] = min(dp[i][j], dp[i][k] + dp[k][j]);
}

int main()
{
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++)
        {
            if (i == j)dp[i][j] = 0;
            else dp[i][j] = INF;
        }

    for (int i = 2; i <= n; i++)
    {
        int x, y, z;
        cin >> x >> y >> z;
        dp[x][y] = z;
        dp[y][x] = z;
    }

    floyd();

    while (m--)
    {
        int x, y;
        cin >> x >> y;
        if (dp[x][y] == INF)
            cout << dp[y][x] << endl;
        else
            cout << dp[x][y] << endl;
    }
    return 0;
}

K:

#include 
#include 
#include 
#include 
#include
using namespace std;
string a;
int main()
{
    string s;
    cin>>s;
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        string res;
        for(int i=0;i

L:

#include 
#include 
#include 

using namespace std;

const int N = 3000 + 5;

int a[N][N];
int row[N], col[N];
int n, m;

int main() {
    while(scanf("%d%d", &n, &m) != EOF) {
  for(int i = 0; i < n; i ++ )
  {
   row[i] = 0;
  }
  for(int j = 0; j < m; j ++ ) col[j] = 0;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                scanf("%d", &a[i][j]);
                row[i] += a[i][j];//求每一行的最大值
                col[j] += a[i][j];//求每一列的最大值
            }
        }
        int ans = 0;
        for(int i=0; i

M:好我是菜逼,我以为这题是动态规划没解出来看了看答案是贪心

简单来说就是从前往后推 ,只考虑当前的字符,是就不变,不是就变,后面是啥也影响不了我

#include 
#include 
#include 
#include 
using namespace std;
const int N = 1010;
typedef pair PII;
string a,b;
vector q;
void rev(int i){
    if(a[i]=='0') a[i]='1';
    else a[i]='0';
}
int main()
{
    
    cin>>a>>b;
    a="?"+a;
    b="?"+b;
    bool flag=false;
    for(int i=1;i

N题:剪枝

可以dp,dp比较爽,这里用的是dfs

#include 
#include 
#include 
using namespace std;
int n,k;
long res=0;
bool st[210];

void dfs(int sum,int u,int last)
{
    if(u==k)
    {
        if(sum==n) res++;
        return ;
    }
    for(int i=last;i<=n-sum;i++)
    {
        dfs(sum+i,u+1,i);
        st[i]=0;
    }
}
int main()
{
    cin>>n>>k;
    dfs(0,0,1);
    cout<

你可能感兴趣的:(算法)