杭电多校总结2021-07-22

1001 I love cube

Problem Description
Give you a cube with a side length of n-1. Find the number of equilateral triangles with three points on the cube point. Each side must be parallel to a certain surface of Oxy, Oxz, Oyz. Now you need to count how many such triangles there are.Each point can only be on the boundary or inner point of the cube, and the three coordinates x, y, and z of each point must be integers.

Input
The first line contains an integer T(T<=1e5) . Then T test cases
follow.

Each test case contains a single Integer n(0<=n<=1e18).

If n=0, output 0

Output
For each case, print an integer, which is the answer modulo 109+7

Sample Input
2
1
2

Sample Output
0
8

签到题。看清楚他问什么,边长为n-1的正方体(立方体),求满足条件的的等边三角形的个数,等边三角形的点只能在边界和内部,不能在外部。最后求出一个3次方求和的公式。用_int 128也可以,套用一下输入输出的板子就行了。在这里插入图片描述
因为n在10的18次方范围内,所以选择unsigned long long,并且首先对n作取模。

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

const int mod = 1e9 + 7;

void solve()
{
    ll n;
    scanf("%lld",&n);
    n --;
    ll a = n, b = n + 1;
    ll x = ((a % mod) * (b % mod)) % mod;
    ll res = x * x % mod;
    printf("%lld\n",(res * 2) % mod);
}

int main()
{
    //freopen("1001.txt","r",stdin);
    int t;
    cin >> t;
    while(t -- )
    {
        solve();
    }
    return 0;
}

1005 I love string

** Problem Description**
Mr X likes to play string games.
Mr X has an operation sequence. This operation sequence can be writtenas a string. For each operation, the next character of the operationsequence can be inserted before or after the current string. For example, my operation sequence is “aabac”, suppose the sequence obtained after the first four operations is “baaa”, then after the last operation, the string may become “baaac” or “cbaaa”. It can beseen that there is only one operation method for the first operation. For other operations, there are only two methods of operation.
For each operation method, there will be a score. The smaller the lexicographic order of the final string, the higher the final score.
Then, for a given operation sequence, how many operation methods can get the maximum score.
The two operation methods are different. If and only if there is a certain operation (not the first operation), one operation will be inserted before the current string, and the other operation will be inserted after the current string.

Input
Enter a positive integer T (T≤10) on the first line to represent the
number of test cases.

For each test case:

the first line contains a integer n (1≤n≤100000) to represent the
length of the string.

the second line contains a string of lowercase letters , which
represents the sequence of operations.

Output
For each test case, output a line of a positive integer to represent the number of schemes, and the answer is modulo 1000000007

容易发现,假设我要模拟出字典序最小的序列,只有最前面一段相同的字符才可以有两种选择,令最初
一段相同的字符长度为,答案就是2^(x-1)。

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

const int mod = 1e9 + 7;

void solve()
{
    int n;
    scanf("%d",&n);
    string s;
    cin >> s;
    int head = -1,hail = -1;
    ll res = 1;
    head = s[0] - 'a',hail = s[0] - 'a';
    for(int i = 1;i < s.size();i ++ )
    {
            int ad = s[i] - 'a';
            if(ad == head && ad == hail)
            {
                res = (res * 2) % mod;
            }
            else if(ad <= head)
            {
                head = ad;
                //res ++;
            }
            else if(ad >= hail)
            {
                hail = ad;
                //res ++;
            }
            else
            {
                hail = ad;
                //res ++;
            }
        }
    printf("%lld\n",res % mod);
}

int main()
{
    int t;
    cin >>t;
    while(t -- )
    {
        solve();
    }
    return 0;
}

1008 I love exam

** Problem Description**
Student Z doesn’t love exams

The exam was about to be done soon, but student Z didn’t even read the
book, He had collapsed.

Student Z has a total of n exams, and there are still t days before
the start of the exam, which means he still has t days to PREVIEW.

But student Z couldn’t even read the textbooks, and couldn’t review it
at all. Fortunately, a kind classmate gave him m sets of review
materials. The i set of materials can improve the grades of the si
course. The i set of materials needs to be studied for yi days. You
can increase xi points later (the upper limit of each course is 100
points, so after it is upgraded to 100 points, there will be no
further increase).and note that each set of review materials can only
be used once.

Student Z now has a zero-point level in every course. it is impossible
to review all the materials, so he needs to choose some materials to
review, but he can fail at most p courses in this semester (if the
score of one course is less than 60 points will fail), otherwise he
will be talked to by the professor.

Student Z now wants to know the maximum points he can get in all
courses under the premise of fail no more than p courses this
semester. If he cannot meet the conditions, please output −1 .

Input
A positive integer T (T≤10) in the first line represents the number of
test cases.

For each test case:

The first line contains a positive integer n (n≤50) represents the
total number of courses in this semester.

The second line contains n strings which length is no more than 15,
representing the course name of each course in this semester.

The third line contains a positive integer m (m≤15000) represents the
number of review materials he obtained.

In the next m lines, each line have a string s and two positive
integers x(1≤x≤10) and y(1≤y≤10) , representing the course of this set
of materials review, the improved scores and The number of days
required for learning(data assurance this course was studied this
semester ).

The last line has two integers t, p(1≤t≤500,0≤p≤3) represents the
number of review days that student Z has and the upper limit of the
number of failed courses in this semester.

Output
For each test case, output a line with a positive integer representing the maximum score that student Z can obtain in the case of meeting the conditions .If he must be talked to by the professor, output −1。

题意:n个学科,还剩t天,有m种复习材料,求在最多能挂p科的情况下的最大分数
科目-分数-天数用vector来存。两次背包,一次对单个科目进行背包,然后对所有科目背包。

入门dp。
对于每门课,我们可以背包算出在f(i)表示在花费天的情况下,最多能得多少分。
合并每门课的时候,记录g(j,k)表示花费j天,挂了k门课的时候得到的最多分数。
最终转移是O(nt^2p)的。

#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
#include<map>
#include<vector>
using namespace std;
#define ll long long
typedef pair<int,int>pll;
int f[60][550];//第i门,花j天->得分 
int dp[60][550][10];//第i门课,花j天,挂k科->得分 
map<string,int> mp;
signed main()
{
	int t; cin>>t;
	while(t--){
		mp.clear(); 
		vector<pll>a[60];
		memset(f,-0x3f,sizeof f);
		memset(dp,-0x3f,sizeof dp);
		int n; cin>>n;
		for(int i=1;i<=n;i++){
			string s; cin>>s;
			mp[s]=i;
		}
		int m; cin>>m;
		for(int i=1;i<=m;i++){
			string s;
			int x,y;
			cin>>s>>x>>y;
			a[mp[s]].push_back({x,y});
		}
		int T,P; cin>>T>>P;
		for(int i=1;i<=n;i++) f[i][0]=0;
		for(int i=1;i<=n;i++){
			for(int j=0;j<a[i].size();j++){
				for(int k=T;k>=a[i][j].second;k--){
					f[i][k]=min(100,max(f[i][k],f[i][k-a[i][j].second]+a[i][j].first));
				}
			}
		} 
		dp[0][0][0]=0;
		for(int i=1;i<=n;i++){//第几门课
			for(int j=0;j<=T;j++){//花了几天 
				for(int k=0;k<=P;k++){
					for(int z=0;z<=j;z++){
						if(f[i][z]<60&&k!=0) dp[i][j][k]=max(dp[i][j][k],dp[i-1][j-z][k-1]+f[i][z]);
						else if(f[i][z]>=60) dp[i][j][k]=max(dp[i][j][k],dp[i-1][j-z][k]+f[i][z]);
					}
				}
			}
		}
		int ans=-1;
		for(int i=0;i<=P;i++){
			ans=max(ans,dp[n][T][i]);
		}
		cout<<ans<<endl;
	}
}

1011 I love max and multiply

** Problem Description**
Mr.I has two sequence Ai and Bi of length n,(0≤i≤n−1).

Define an array C of length n, where Ck=max{AiBj}, satisfying (i&j≥k).

& is the button under binary Bitwise AND operation.

Please calculate the value of ∑n−1i=0Ci, modulo 998244353.

Input
The first line contains an integer T . Then T test cases follow.

Each test case contains three lines.

The first one contains an integer n(1≤n≤218) — length of the array a.

The second one contains n integers A0,A1,A2,…,An−1(|Ai|≤109)

The third one contains n integers B0,B1,B2,…,Bn−1(|Bi|≤109)

∑n≤219

Output
For each test case, output a single integer ans,where ans=∑n−1i=0Ci modulo 998244353.

参照https://blog.csdn.net/weixin_50547586/article/details/119065045

这道题最暴力的写法是枚举,记录每个 i and j 的值,然后在每个位置上存最大的。 最后从n-1开始跑到0每次加上前面最大值即可。

但是显然会T,有没有一种更快的方法呢?

想到更快的解法关键点就是处理。

我们先给出一个结论:任意两个数and后的值一定比它们都小。

所以我们可以先确定k,再来分析 i 和 j 。

假设k的二进制是,那么 i 和 j 的二进制一定是这种形式:,其中 表示可以是0 也可以是 1 。

所以这里提出一个想法:我可以用中的最大值来表示,从而使得最大。

下面模拟解释一下上面这个想法。

我们先确定 i ,假是 i 的值就是 1010110,我们来分析 j 。

我们可以任意改变1010110中的0,因为不管怎么变,只要原本是1的位置不变成0,的值就还是 i 。我们现在要做的事找到比1010110大的数的最大值。(因为只能将0变1,所以一定是比i更大的数)。但是现在问题来了,我们该怎么选择0的位置将它变成1呢?这个方案数会随着0的个数而指数增长。所以暴力枚举是不可能的。

我们可以用一种dp的思想去思考这个问题。我们可以从大到小的枚举,也就是从n-1枚举到0。

这样我们就可以通过每次改变一位0的方式来找到前面的最大值。

比如:

我们要找100101前的最大值,假如我们改变两个0的位置:111101(第二位和第三位),又因为我们是从大到小枚举的,所以在100101之前我们已经枚举过101101或者110101,所以改变两个位置的111101完全会由101101和110101来继承,所以我们每次只用改变一位0就可以了。

看到这里肯定由人会问,这是固定了 i 的值,但 i 的是不是固定的呀!

确实如此,但是这样想,i 的值只能比现在的值更大,也就是原本是0的位置上变成1,这样就有可能的值不等于 i 了。那么现在我想问一下,iandj的值是变大了还是变小了呢?显然是变大的,于是变大的值对我们的影响是什么样子的呢?这个问题可以好好想想。(狗头)

想清楚这些点,这道题就解出来了。


#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define mod 998244353
#define INF 1e18
int main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	int T;
	cin >> T;
	while (T--) {
		int n;
		cin >> n;
		vector<ll>v1((n + 1)<<1),V1((n+1)<<1),V2((n+1)<<1), v2((n + 1)<<1);
		for (int i = 0; i < n; i++) {
			cin >> v1[i];
			V1[i] = v1[i];
		}
		for (int i = 0; i < n; i++) {
			cin >> v2[i];
			V2[i] = v2[i];
		}
		int m = 0;
		while ((1 << m) <= n)m++;
		for (int i = n ; i <= (1 << m) - 1; i++) {
			V1[i] = V2[i] = -INF;
			v1[i] = v2[i] = INF;
		}
		for (int i = n-1; i >= 0; i--) {
			for (int j = 0; j < m; j++) {
				ll kase = (1 << j)&i;
				if (!kase) {
					V1[i] = max(V1[i], V1[i ^ (1 << j)]);
					V2[i] = max(V2[i], V2[i ^ (1 << j)]);
					v1[i] = min(v1[i], v1[i ^ (1 << j)]);
					v2[i] = min(v2[i], v2[i ^ (1 << j)]);
				}
			}
		}
		ll ans = -INF;
		ll cnt = 0;
		for (int i = n-1; i >= 0; i--) {
			//ans = -INF;
			ans = max(V1[i] * V2[i], ans);
			ans = max(V1[i] * v2[i], ans);
			ans = max(v1[i] * V2[i], ans);
			ans = max(v1[i] * v2[i], ans);
			cnt += ans%mod;
			cnt = (cnt + mod) % mod;
			cnt %= mod;
 
		}
		cout << cnt << endl;
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值