Problem B
题目
You are playing one RPG from the 2010s. You are planning to raise your smithing skill, so you need as many resources as possible. So how to get resources? By stealing, of course.
You decided to rob a town's blacksmith and you take a follower with you. You can carry at most p units and your follower — at most f units.
In the blacksmith shop, you found cnts swords and cntw war axes. Each sword weights s units and each war axe — w units. You don't care what to take, since each of them will melt into one steel ingot.
What is the maximum number of weapons (both swords and war axes) you and your follower can carry out from the shop?
Input
The first line contains a single integer t (1≤t≤104) — the number of test cases.
The first line of each test case contains two integers p and f (1≤p,f≤109) — yours and your follower's capacities.
The second line of each test case contains two integers cnts and cntw (1≤cnts,cntw≤2⋅105) — the number of swords and war axes in the shop.
The third line of each test case contains two integers s and w (1≤s,w≤109) — the weights of each sword and each war axe.
It's guaranteed that the total number of swords and the total number of war axes in all test cases don't exceed 2⋅105.
Output
For each test case, print the maximum number of weapons (both swords and war axes) you and your follower can carry.
思路
上来有点懵逼,想写dp却发现并不是很好写。贪心的话也没什么思路,不敢暴力枚举....然后什么都干不了,但题解就是暴力枚举加一点小贪心,直觉告诉我们价值小的一定相对优,那么我们先判断拿不拿的完小的,拿不完直接输出拿的数量,拿的完就枚举每个人拿的小的数量然后剩余的去拿大的,算总数。
Problem C
Consider the following process. You have a binary string (a string where each character is either 0 or 1) w of length n and an integer x. You build a new binary string s consisting of n characters. The i-th character of s is chosen as follows:
if the character wi−x exists and is equal to 1, then si is 1 (formally, if i>x and wi−x= 1, then si= 1);
if the character wi+x exists and is equal to 1, then si is 1 (formally, if i+x≤n and wi+x= 1, then si= 1);
if both of the aforementioned conditions are false, then si is 0.
You are given the integer x and the resulting string s. Reconstruct the original string w.
Input
The first line contains one integer t (1≤t≤1000) — the number of test cases.
Each test case consists of two lines. The first line contains the resulting string s (2≤|s|≤105, each character of s is either 0 or 1). The second line contains one integer x (1≤x≤|s|−1).
The total length of all strings s in the input does not exceed 105.
Output
For each test case, print the answer on a separate line as follows:
if no string w can produce the string s at the end of the process, print −1;
otherwise, print the binary string w consisting of |s| characters. If there are multiple answers, print any of them.
思路
给我们一个已经构造好的01串,让我们反推原串,那么很显然如果一个点的左右两个要求点都不存在,但是这个点的值为1那么显然是不存在的,然后我们考虑比较特殊的1-k长度的两边,这两边的话,他的结果会被唯一确定,因为只有一个点会影响到他,那么我们进行判断,同时更改答案串的值,然后就是中间的点,他会有左右两边,如果两边都不符合答案就返回不存在,否则只要有一边可以我们就更新。
代码实现
#include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
#define rep(i,f_start,f_end) for (int i=f_start;i<=f_end;++i)
#define per(i,n,a) for (int i=n;i>=a;i--)
#define MT(x,i) memset(x,i,sizeof(x) )
#define rev(i,start,end) for (int i=start;i<end;i++)
#define inf 0x3f3f3f3f
#define mp(x,y) make_pair(x,y)
#define lowbit(x) (x&-x)
#define MOD 1000000007
#define exp 1e-8
#define N 1000005
#define fi first
#define se second
#define pb push_back
typedef long long ll;
typedef vector <int> VI;
typedef pair<int ,int> PII;
typedef pair<int ,PII> PIII;
ll gcd (ll a,ll b) {return b?gcd (b,a%b):a; }
inline int read() {
char ch=getchar(); int x=0, f=1;
while(ch<'0'||ch>'9') {
if(ch=='-') f=-1;
ch=getchar();
} while('0'<=ch&&ch<='9') {
x=x*10+ch-'0';
ch=getchar();
} return x*f;
}
const int maxn=1e5+10;
int flag;
int n,x;
int ct[maxn];
char s[maxn];
inline void solve (int k) {
int cnt=0;
if (k-x>=1) cnt++;
if (k+x<=n) cnt++;
if (cnt==0) {
if (s[k]=='1') flag=0;
return ;
}
else if (cnt==1) {
if (k-x>=1) {
if (ct[k-x]!=-1&&ct[k-x]!=s[k]-'0') flag=0;
ct[k-x]=s[k]-'0';
}
else {
if (ct[k+x]!=-1&&ct[k+x]!=s[k]-'0') flag=0;
ct[k+x]=s[k]-'0';
}
}
else {
if (s[k]=='0') {
if (ct[k+x]==1) flag=0;
if (ct[k-x]==1) flag=0;
ct[k-x]=0,ct[k+x]=0;
}
else {
if (ct[k-x]!=0) {
ct[k-x]=1;
return ;
}
if (ct[k+x]==0) flag=0;
ct[k+x]=1;
}
}
}
int main () {
int t;
cin>>t;
while (t--) {
flag=1;
scanf ("%s",s+1);
scanf ("%d",&x);
n=strlen (s+1);
rep (i,1,n) ct[i]=-1;
rep (i,1,n) solve (i);
if (flag) {
rep (i,1,n) {
if (ct[i]==-1) {
ct[i]=1;
}
printf ("%d",ct[i]);
}
printf ("
");
}
else {
printf ("-1
");
}
}
return 0;
}
Problem D
题目
You are given an array a1,a2…an. Calculate the number of tuples (i,j,k,l) such that:
1≤i<j<k<l≤n;
ai=ak and aj=al;
Input
The first line contains a single integer t (1≤t≤100) — the number of test cases.
The first line of each test case contains a single integer n (4≤n≤3000) — the size of the array a.
The second line of each test case contains n integers a1,a2,…,an (1≤ai≤n) — the array a.
It's guaranteed that the sum of n in one test doesn't exceed 3000.
思路
首先可以发现,我们需要表示出一个数在某段区间的出现次数,那么我们先对这个序列可能出现的所有数的次数,累加一个前缀和。然后把四个点画在坐标上,你会发现,有一部分匹配的点会被截断,因为j需要大于i且小于k,那么我们考虑枚举j的点,然后这样我们就可以算出k-l之间和和a[j]相等的数的数目最大值,同理算出左边的,那么他们相乘就是总的数目。
代码实现
#include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
#define rep(i,f_start,f_end) for (int i=f_start;i<=f_end;++i)
#define per(i,n,a) for (int i=n;i>=a;i--)
#define MT(x,i) memset(x,i,sizeof(x) )
#define rev(i,start,end) for (int i=start;i<end;i++)
#define inf 0x3f3f3f3f
#define mp(x,y) make_pair(x,y)
#define lowbit(x) (x&-x)
#define MOD 1000000007
#define exp 1e-8
#define N 1000005
#define fi first
#define se second
#define pb push_back
typedef long long ll;
typedef vector <int> VI;
typedef pair<int ,int> PII;
typedef pair<int ,PII> PIII;
ll gcd (ll a,ll b) {return b?gcd (b,a%b):a; }
inline int read() {
char ch=getchar(); int x=0, f=1;
while(ch<'0'||ch>'9') {
if(ch=='-') f=-1;
ch=getchar();
} while('0'<=ch&&ch<='9') {
x=x*10+ch-'0';
ch=getchar();
} return x*f;
}
const int maxn=5010;
int a[maxn];
int pre[maxn][maxn];
int main () {
int t;
cin>>t;
while (t--) {
int n;
scanf ("%d",&n);
ll ans=0;
rep (i,1,n) scanf ("%d",&a[i]);
rep (i,1,n)
rep (j,1,3000) {
if (a[i]==j) pre[i][j]=pre[i-1][j]+1;
else pre[i][j]=pre[i-1][j];
}
rep (j,1,n)
rep (k,j+1,n) {
ll r=pre[n][a[j]]-pre[k][a[j]];
ll l=pre[j-1][a[k]];
ans+=l*r;
}
printf ("%lld
",ans);
}
return 0;
}