The 2022 SDUT Summer Trials
1.
结论:两个数分别除以他们的最大公约数,商是互质数。
void slove()
{
int x, y;
cin >> x >> y;
cout << __gcd(x,y) << endl;
}
2.
可以用dp,定义dp[ i ]位以i结尾的最大价值。很明显转移方程就是找到第一个小于a[ i ]的 a[ j ]就可以,因为大于a[ i ] 的都要变成a[i]。
那如何找到j的位置,可以用一个单调栈维护单调递增的序列即可。我比你小又比你近你肯定就没有机会了。所以是单调递增。
void slove()
{
int n;
cin >> n;
fel(i,1,n) cin >> a[i];
stack< pair<int,int> >s;
s.push({0, 0});
int ans=0;
for(int i = 1;i <= n; i++){
while(s.size()&&s.top().first>=a[i]) s.pop();
auto [x, y] = s.top();
f[i] = f[y] + ( i - y ) *a[i];
ans = max( ans, f[i] );
s.push({ a[i], i });
}
cout<<ans<<endl;
}
3.
这属实是好题呀。写他的第二天碰到了一个差不太多的题目。
首先来看值域值域很小,抽屉原理明显的。最多1e5个值。所以直接考虑什么时候开始出现重复,很明显当数列长度为n的时候选择为2^n次方。考虑到这个,当n大于=17的时候是130000多 > 1e5所以当n大于17,肯定有解,所以就看小于17直接二进制枚举暴力求解即可。
void slove(){
cin >> n >> k;
fel(i,1,n) cin >> a[i];
if(n >= 17){
cout << "YES" << endl;
return;
}
int flag = 0;
for(int i = 1; i < (1<<n); i++){
int sum=0;
for(int j=1; j <= n; j++){
if(( i>>(j-1) ) & 1){
sum = (sum + a[j]) % k;
}
}
mp[sum]++;
if(mp[sum] > 1){
flag = 1;
break;
}
}
cout << (flag?"YES":"NO") << endl;
}
4.
void slove()
{
cin >> n;
fel(i,1,n) cin >> a[i] >> k[i];
int ans = 0;
fel(i,1,n){
fel(j,i+1,n){
if(a[i] != a[j]){
ans++;
}
}
}
cout<<ans<<endl;
}
5.
很明显奇数不行。考虑偶数。
看第一个例子发现每次可以确定一个点然后会确定一些相关的点。每个点的选择是2。最后就是2的m次方。
void slove(){
cin >> n;
int flag = 0;
fel(i,1,n)
{
cin >> a[i];
if (a[i] == i) flag = 1;
}
if(n % 2 || flag){
cout<<0<<endl;
return;
}
int ans = 1;
for(int i = 1;i <= n; i++){
int j = i;
if(vis[j] == 0){
ans=(ans*2)%mod;
while(vis[j] == 0){
vis[j] = 1;
j = a[j];
}
}
}
cout<<ans<<endl;
}
6.
不会写看的题解,感觉很莫名奇妙。我应该把所有情况都讨论了呀。
而且答案是错的,应该输出1,2,3呀?感觉官方题解有个地方想错了。如果全是负数的话应该单独拿出来讨论。
首先如果存在奇数同时存在正数的话肯定考虑用那个去取一个最大正数,这样你肯定可以保证结果是更优的。然后剩余的k就每次取两个。因为负数取的个数肯定是偶数更优的。给出自己的代码吧,虽然错了,可能是出题人没想到这种情况。
bool cmp(node x,node y){
if(x.val==y.val){
if(x.val>=0){
return x.id>y.id;
}
else{
x.id<y.id;
}
}
return x.val<y.val;
}
bool cmp2(node x,node y){
if(x.val==y.val){
return x.id<y.id;
}
return x.val>y.val;
}
void slove(){
cin>>s;
cin>>k;
int len=s.length(),cnt=0;
for(int i=0;i<len;i++){
if(s[i]=='|') continue;
int j=i,sum=0,flag=1;
while(j<len&&s[j]!='|'){
if(s[j]=='-') flag=-1;
else{
sum=sum*10+(s[j]-'0');
}
j++;
}
j--;
i=j;
b[++cnt]={sum*flag,cnt};
a[cnt] = sum;
}