C
题意:给一个长度为n的数组,找长度为k的子数组,在有限的操作下使数组里面的数全都变成0,输出所有可能k的情况。
思路:对于每一次减法,相当于可以把1变成0,假设某一位上一共有x个1,那么为了将x个1全部变为0,那么x一定是k的倍数,所有只要保证k是所有位最大公约数的约数就行了。
#include <bits/stdc++.h>
using namespace std ;
const int N = 2e5 + 10 ;
int n ;
int s[35] ;
int main()
{
int t ;
cin >> t ;
while (t -- ){
cin >> n ;
memset(s, 0, sizeof s) ;
for (int i = 1; i <= n; i ++ ) {
long long a ;
cin >> a ;
for (int j = 0; j < 30; j ++ )
if (a >> j & 1) s[j] ++ ;
}
int d = 0 ;
for (int i = 0; i < 30 ;i ++ ) d = __gcd(d, s[i]) ;
if (!d) {
for (int i = 1; i <= n; i ++ ) cout << i << " " ;
}
else for (int i = 1; i <= d; i ++ ) {
if (d % i == 0) cout << i << " " ;
}
cout << endl ;
}
return 0 ;
}
D
题意:在深度为n的井中有一个青蛙,有两个数组
a
i
a_i
ai和
b
i
b_i
bi,
a
i
a_i
ai表示在深i米的地方青蛙能往前跳0~
a
i
a_i
ai(包括0和
a
i
a_i
ai)米,
b
i
b_i
bi表示青蛙在深度为i的地方会往下滑
b
i
b_i
bi米。
思路:bfs暴搜,
#include <bits/stdc++.h>
#define x first
#define y second
using namespace std ;
typedef pair<int, int>PII ;
const int N = 3e5 + 10 ;
int n, m, a[N], b[N] ;
int ans[N] ;
int res ;
void print(int u) {
if (!ans[u]) return ;
print(ans[u]) ;
cout << u << " " ;
}
void cnt(int u) {
if (!ans[u]) return ;
cnt(ans[u]) ;
res ++ ;
}
int main(){
cin >> n ;
for (int i = 1; i <= n; i ++ ) cin >> a[i] ;
for (int i = 1; i <= n; i ++ ) cin >> b[i] ;
int mn = n ;
queue<PII>q ;
q.push({n, n}) ;
while (q.size()) {
auto t = q.front() ;
q.pop() ;
if (t.x == 0) {
cnt(0) ;
cout << res << endl ;
print(0) ;
return 0 ;
}
for (int i = a[t.x]; i > 0; i -- ){
int pos = t.x - i ;
if (pos < 0) pos = 0 ;
if (pos >= mn) break ;
ans[pos] = t.y ;
q.push({pos + b[pos], pos}) ;
}
mn = min(mn, t.x - a[t.x]) ;
}
cout << -1 << endl ;
return 0 ;
}