A.
已知 gcd(a,b) 共递归了 n次,求所有可能的a,b中满足a>b>=0且a+b最小的一组的a与b之和。
思路:枚举几个就发现是斐波那契数列 打个表就好了 而且这个n <= 80 很耐人寻味 斐波那契数列小于80的时候LL是存的下的
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <stack>
#include <queue>
using namespace std;
typedef long long LL ;
typedef pair<int,int> pii;
#define fi first
#define se second
const int INF = 0x3f3f3f3f;
const double eps = 1e-7;
const double pi=acos(-1);
const int N = 3005;
const int M = 2005;
const int mod = 1e9+7;
LL f[105];
int main()
{
int t ;
f[0] = 1,f[1] = 3,f[2] = 5;
for(int i = 3; i < 81 ;i ++)
f[i] = f[i-1]+f[i-2];
cin >> t;
while(t --)
{
LL n;
cin >> n;
cout << f[n] << '\n';
}
return 0;
}
B.
题意:括号匹配
思路:用栈模拟就好 左括号全部入栈 如果遇到右括号 就判断当前栈是否为空(这个很重要 空栈弹出会报RE的)栈顶元素是否匹配 最后再检查栈内的元素是否全部匹配完就好了
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <stack>
#include <queue>
using namespace std;
typedef long long LL ;
typedef pair<int,int> pii;
#define fi first
#define se second
const int INF = 0x3f3f3f3f;
const double eps = 1e-7;
const double pi=acos(-1);
const int N = 3005;
const int M = 2005;
const int mod = 1e9+7;
char s[1000005];
stack <char> st;
int main()
{
scanf("%s",s);
bool flag = 0;
int len = strlen(s);
if(len == 0)
{
cout << "Yes" << '\n';
return 0;
}
if(len == 1)
{
cout << "No" << '\n';
return 0;
}
for(int i = 0; i < len; i ++)
{
if(s[i] == '(')
st.push(s[i]);
if(s[i] == '[')
st.push(s[i]);
if(s[i] == '{')
st.push(s[i]);
if(s[i] == ')')
{
if(!st.empty() && st.top() == '(')
st.pop();
else
{
flag = 1;
break;
}
}
if(s[i] == ']')
{
if(!st.empty() && st.top() == '[')
st.pop();
else
{
flag = 1;
break;
}
}
if(s[i] == '}')
{
if(!st.empty() && st.top() == '{')
st.pop();
else
{
flag = 1;
break;
}
}
}
if(!flag && st.empty())
cout << "Yes" << '\n';
else
cout << "No" << '\n';
return 0;
}
C.
题意:给一个长度为n的序列 求长度为k的连续字段乘积对998244353取模的最大值
思路:两种思路,但本质都是维护一个长度为k的字段 1是用线段树维护 2.是直接维护 但会出现逆元 所以会更麻烦些
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <stack>
#include <queue>
using namespace std;
typedef long long LL ;
typedef pair<int,int> pii;
#define fi first
#define se second
const int INF = 0x3f3f3f3f;
const double eps = 1e-7;
const double pi=acos(-1);
const int N = 2e5+5;
const int M = 2005;
const int mod = 998244353;
struct node
{
int l,r;
LL x;
LL sum;
}t[N << 2];
void build(int v,int l,int r)
{
t[v].l = l;
t[v].r = r;
if(l == r)
{
scanf("%lld",&t[v].x);
t[v].sum = t[v].x;
return ;
}
int mid = l+r>>1;
build(v << 1,l,mid);
build(v << 1|1,mid+1,r);
t[v].sum = t[v<<1].sum*t[v<<1|1].sum%mod;///父节点的值为左右结点的乘积
}
LL query(int v,int x,int y)
{
if(t[v].l == x && t[v].r == y)
{
return t[v].sum ;
}
int mid = t[v].l+t[v].r >> 1;
if(y <= mid)
query(v << 1,x,y);
else
{
if(x > mid)
query(v << 1|1,x,y);
else
return query(v << 1,x,mid)*query(v << 1|1,mid+1,y)%mod;
}
}
int main()
{
int n,k;
cin >> n >> k;
build(1,1,n);
LL res = 0;
for(int i = 1;i <= n-k+1;i ++)
{
res = max(res,query(1,i,i+k-1));
}
printf("%lld\n",res);
return 0;
}
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <stack>
#include <queue>
using namespace std;
typedef long long LL ;
typedef pair<int,int> pii;
#define fi first
#define se second
const int INF = 0x3f3f3f3f;
const double eps = 1e-7;
const double pi=acos(-1);
const int N = 2e5+5;
const int M = 2005;
const LL mod = 998244353;
LL a[1000010];
LL quickpow(LL a,LL b)
{
LL res = 1;
while(b)
{
if(b&1)
res = res*a%mod;
b >>= 1;
a = a*a%mod;
}
return res;
}
int main()
{
ios::sync_with_stdio(false);
int n,k;
cin >> n >> k;
LL res = 0;
LL temp = 1;
LL cnt = 0;
for(int i = 1;i <= n;i ++)
{
cin >> a[i];
if(a[i] == 0)
temp = 1,cnt = 0;
else
{
cnt ++ ;
temp = temp*a[i]%mod;
if(cnt == k)
{
res = max(res,temp);
temp = temp*quickpow(a[i-k+1],mod-2)%mod;///处理逆元
cnt -- ;
}
}
}
printf("%lld\n",res);
return 0;
}
D.
题意:给出长度n的序列 求有多少个不同的l,r序列异或和为0
思路:先求出前缀异或和 根据题意 sum[r] ^ sum[l-1] = 0 所以 sum[r] = sum[l-1]
遍历一遍用map标记有多少个数为相同的前缀异或值
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <stack>
#include <queue>
using namespace std;
typedef long long LL ;
typedef pair<int,int> pii;
#define fi first
#define se second
const int INF = 0x3f3f3f3f;
const double eps = 1e-7;
const double pi=acos(-1);
const int N = 2e5+5;
const int M = 2005;
const LL mod = 998244353;
LL a[200010];
map <LL,int> mp;
int main()
{
int n;
cin >> n;
LL now = 0;
LL res = 0;
mp[0] = 1;
for(int i = 0;i < n;i ++)
{
int x;
cin >> x;
now ^= x;
res += mp[now];
mp[now] += 1;
}
cout << res << '\n';
return 0;
}
D.
思路:贪心模拟 尽量 把小的数放在最高位置上 大的数放在低位置上就好
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <stack>
#include <queue>
using namespace std;
typedef long long LL ;
typedef pair<int,int> pii;
#define fi first
#define se second
const int INF = 0x3f3f3f3f;
const double eps = 1e-7;
const double pi=acos(-1);
const int N = 5e5+5;
const int M = 2005;
const int mod = 1e9+7;
int pos,cnt;
char a[N],s[N];
int b[N];
int main()
{
scanf("%s",a+1);
int len = strlen(a+1);
for(int i = 1;i <= len;i ++)
{
if(a[i] != '+')
s[++cnt] = a[i];
}
sort(s+1,s+cnt+1);
pos = len-cnt+1;
/// printf("pos %d\n",pos);
for(int i = cnt,tail = 1;i > 0;i -= pos ,tail ++)
{
for(int j = i;j > max(0,i-pos);j --)
{
// printf("i %d %c\n",i,s[j]);
b[tail] += s[j]-'0';
}
}
for(int i = 1;i <= 500050;i ++)
{
if(!b[i])
{
pos = i;
break;
}
b[i+1] += b[i]/10;
b[i] %= 10;
}
for(int i = pos-1;i > 0;i --)
{
printf("%d",b[i]);
}
printf("\n");
return 0;
}