题目: 给你一个数组A,让你构造一个数组B,使得A[1] * B[1] + A[2] * B[2] + …A[n] * B[n] = 0,A数组和B数组里面都没有0?思路: 如果n是偶数就对于每一个i直接构造B[i]和B[i + 1]使得B[i] * A[i] = A[i + 1] * B[i],求A[i]和A[i +1]的最小公倍数,然后除一下就行 如果是奇数的话,就让最后三个构造出一个A[n - 2] * x + A[n - 1] * y = A[n] * z,其他的就按偶数来写就行, 这道题的代码写的有点啰嗦,不太好代码:
# include <bits/stdc++.h>
# define fi first
# define se second
# define endl '\n'
# define all ( x) x. begin ( ) , x. end ( )
# define pb push_back
# define PII pair< int , int >
# define int long long
# define ios ios:: sync_with_stdio ( false ) ; cin. tie ( 0 ) ; cout. tie ( 0 )
using namespace std;
const int N = 2e5 + 100 , mod = 1e9 + 7 ;
int gcd ( int a, int b)
{
if ( b == 0 ) return a;
return gcd ( b, a % b) ;
}
int lcm ( int a, int b)
{
int w = a / gcd ( ( int ) a, ( int ) b) * b;
return w;
}
void solve ( )
{
int n; cin >> n;
vector< int > a ( n + 1 ) ;
for ( int i = 1 ; i <= n; i ++ ) cin >> a[ i] ;
vector< int > res;
for ( int i = 1 ; i <= n; i += 2 )
{
if ( n % 2 == 1 && i == n - 2 )
{
int f = 0 ;
int k = a[ n - 2 ] + a[ n - 1 ] ;
int q = abs ( k) ;
if ( q == 0 )
{
q = abs ( k + a[ n - 1 ] ) ;
f = 1 ;
}
int w = abs ( a[ n] ) ;
int s = lcm ( q, w) ;
if ( f)
{
if ( k + a[ n - 1 ] > 0 && a[ n] > 0 )
{
res. pb ( s / q) , res. pb ( s / q * 2 ) ;
res. pb ( s / w * - 1 ) ;
}
else if ( k + a[ n - 1 ] > 0 || a[ n] > 0 )
{
res. pb ( s / q) , res. pb ( s / q * 2 ) ;
res. pb ( s / w) ;
}
else if ( k + a[ n - 1 ] < 0 && a[ n] < 0 )
{
res. pb ( s / q) , res. pb ( s / q * 2 ) ;
res. pb ( s / w * - 1 ) ;
}
}
else
{
if ( k > 0 && a[ n] > 0 )
{
res. pb ( s / q) , res. pb ( s / q ) ;
res. pb ( s / w * - 1 ) ;
}
else if ( k > 0 || a[ n] > 0 )
{
res. pb ( s / q) , res. pb ( s / q ) ;
res. pb ( s / w) ;
}
else if ( k < 0 && a[ n] < 0 )
{
res. pb ( s / q) , res. pb ( s / q ) ;
res. pb ( s / w * - 1 ) ;
}
}
break ;
}
int q = abs ( a[ i] ) , w = abs ( a[ i + 1 ] ) ;
int s = lcm ( q, w) ;
if ( a[ i] > 0 && a[ i + 1 ] > 0 ) res. pb ( s / q) , res. pb ( s / w * - 1 ) ;
else if ( a[ i] > 0 || a[ i + 1 ] > 0 ) res. pb ( s / q) , res. pb ( s / w) ;
else if ( a[ i] < 0 && a[ i + 1 ] < 0 ) res. pb ( s / q) , res. pb ( s / w * - 1 ) ;
}
for ( int i = 0 ; i < res. size ( ) ; i ++ )
cout << res[ i] << ' ' ;
cout << endl;
}
signed main ( )
{
ios; int T; cin >> T;
while ( T -- ) solve ( ) ;
return 0 ;
}
题目: 给你a,b,x,你可以执行这个操作 a = abs(a - b),或者b = abs(a - b),问你有没有可能使得 a 或者 b 等于x思路: 观察发现 x 如果在[a , b]之间的话,就可以用一个等差数列来求,x是否在这个区间,公差为 - min(a,b),首项为 max(a,b) 如果x不在这个范围内的话,就让b不断的靠近a,然后把然后使得b接替原来a的位置,a就等于b - a,这个操作也是可以用等差数列来求解的代码:
# include <bits/stdc++.h>
# define fi first
# define se second
# define endl '\n'
# define all ( x) x. begin ( ) , x. end ( )
# define pb push_back
# define PII pair< int , int >
# define int long long
# define ios ios:: sync_with_stdio ( false ) ; cin. tie ( 0 ) ; cout. tie ( 0 )
using namespace std;
const int N = 2e5 + 100 , mod = 1e9 + 7 ;
bool check ( int a, int b, int x)
{
if ( a == 0 || b == 0 ) return false ;
if ( a == x || b == x) return true ;
if ( x < a)
{
int k = b / a;
int w = a + b - a * k;
int c = w - a;
b = a;
a = c;
if ( check ( a, b, x) ) return true ;
return false ;
}
else if ( x >= a && x <= b)
{
int w = ( a + b - x) / a;
int s = a + b - w * a;
if ( s == x) return true ;
else return false ;
}
else
return false ;
return false ;
}
void solve ( )
{
int a, b, x; cin >> a >> b >> x;
if ( a > b) swap ( a, b) ;
if ( check ( a, b, x) ) cout << "YES" << endl;
else cout << "NO" << endl;
}
signed main ( )
{
ios; int T; cin >> T;
while ( T -- ) solve ( ) ;
return 0 ;
}
题目: 有n个人,第i个人有i元钱,并且想要这个人参加聚会这个人的规矩就是 最多a[i]个人比他富,有b[i]个人比他穷,问你最多能邀请几个人来参加聚会思路: 首先,第i个人有i元钱,这样的话就可以二分枚举人数,观察发现,如果按照钱的数量来从左到右排列的话,发现A[i]是一个递减序列,B[i]是一个递增序列,然后直接暴力枚举符合人数就行,时间复杂度O(n * log(n))代码:
# include <bits/stdc++.h>
# define fi first
# define se second
# define endl '\n'
# define all ( x) x. begin ( ) , x. end ( )
# define pb push_back
# define PII pair< int , int >
# define int long long
# define ios ios:: sync_with_stdio ( false ) ; cin. tie ( 0 ) ; cout. tie ( 0 )
using namespace std;
const int N = 2e5 + 100 , mod = 1e9 + 7 ;
int a[ N] , b[ N] ;
int n;
bool check ( int mid)
{
int d = 0 ;
int q1 = mid - 1 ;
int q2 = 0 ;
for ( int i = 1 ; i <= n; i ++ )
{
if ( a[ i] >= q1 && b[ i] >= q2)
{
d++ ;
q1-- , q2++ ;
}
}
if ( d >= mid) return true ;
return false ;
}
void solve ( )
{
cin >> n;
for ( int i = 1 ; i <= n; i ++ ) cin >> a[ i] >> b[ i] ;
int l = 1 , r = n;
while ( l <= r)
{
int mid = l + r >> 1 ;
if ( check ( mid) )
l = mid + 1 ;
else
r = mid - 1 ;
}
cout << r << endl;
}
signed main ( )
{
ios; int T; cin >> T;
while ( T -- ) solve ( ) ;
return 0 ;
}
题目 : 有n个点,m条边,每次都给你两个点a,b,操作1:如果a,b不在一个联通块里面,就连接一下,操作2:如果a,b在一个连通块里面,那么就可以连接其他的未加入连通块的点,问你最大的连通块有多少个点?思路: 假设到第i条边的时候有cnt个操作2,那答案就是前cnt +1个大的连通块相加.并查集代码:
# include <bits/stdc++.h>
# define fi first
# define se second
# define endl '\n'
# define all ( x) x. begin ( ) , x. end ( )
# define pb push_back
# define PII pair< int , int >
# define int long long
# define ios ios:: sync_with_stdio ( false ) ; cin. tie ( 0 ) ; cout. tie ( 0 )
using namespace std;
const int N = 1e3 + 100 , mod = 1e9 + 7 ;
int p[ N] , num[ N] ;
int cnt = 1 ;
int n, d;
int find ( int x)
{
if ( x != p[ x] ) p[ x] = find ( p[ x] ) ;
return p[ x] ;
}
bool cmp ( int a, int b)
{
return a > b;
}
void add ( int a, int b)
{
a = find ( a) ;
b = find ( b) ;
if ( a != b)
{
p[ a] = b;
num[ b] += num[ a] ;
}
else
cnt++ ;
vector< int > res;
for ( int i = 1 ; i <= n; i ++ )
if ( p[ i] == i)
res. pb ( num[ i] ) ;
sort ( all ( res) , cmp) ;
int sum = 0 ;
int k = res. size ( ) ;
for ( int i = 0 ; i < min ( cnt, k) ; i ++ )
sum += res[ i] ;
cout << sum - 1 << endl;
}
void solve ( )
{
cin >> n >> d;
for ( int i = 1 ; i <= n; i ++ )
{
p[ i] = i; num[ i] = 1 ;
}
for ( int i = 1 ; i <= d; i ++ )
{
int a, b; cin >> a >> b;
add ( a, b) ;
}
}
signed main ( )
{
ios; int T = 1 ;
while ( T -- ) solve ( ) ;
return 0 ;
}
题目 : 有两个地图,n个人,每个人在不同的地图里面都有自己独特的战斗力,每个人可以挑地图战斗,进行n - 1次挑战后,只会留下来一个胜利的人,对于每一个人都询问一下他有没有可能是这个胜利的人.思路: 这个题是今天唯一没有写出来的题,就是思维懂了,但是代码能力这方面不行, 就是a数组排序如果小的是最后的wiiner,那比这个数字大的都有可能是wIner,同理也对b排个序,然后走两遍dfs,最后一定是一个环,遍历这个环就行 就是这个没想到咋用代码实现.代码:(借鉴别人的)
# include <bits/stdc++.h>
# define fi first
# define se second
# define endl '\n'
# define all ( x) x. begin ( ) , x. end ( )
# define pb push_back
# define PII pair< int , int >
# define int long long
# define ios ios:: sync_with_stdio ( false ) ; cin. tie ( 0 ) ; cout. tie ( 0 )
using namespace std;
const int N = 2e5 + 100 , mod = 1e9 + 7 ;
int res[ N] ;
vector< int > d[ N] ;
vector< PII> a, b;
int n;
void dfs ( int u)
{
res[ u] = 1 ;
for ( auto x: d[ u] )
{
if ( ! res[ x] )
dfs ( x) ;
}
}
void init ( )
{
for ( int i = 0 ; i <= n; i ++ )
{
a. clear ( ) , b. clear ( ) ;
d[ i] . clear ( ) ;
res[ i] = 0 ;
}
}
void solve ( )
{
cin >> n;
init ( ) ;
for ( int i = 1 ; i <= n; i ++ )
{
int x; cin >> x;
a. pb ( { x, i} ) ;
}
for ( int i = 1 ; i <= n; i ++ )
{
int x; cin >> x;
b. pb ( { x, i} ) ;
}
sort ( all ( a) ) ; sort ( all ( b) ) ;
for ( int i = 0 ; i < n - 1 ; i ++ )
{
d[ a[ i] . se] . pb ( a[ i + 1 ] . se) ;
d[ b[ i] . se] . pb ( b[ i + 1 ] . se) ;
}
dfs ( a[ n - 1 ] . se) ; dfs ( b[ n - 1 ] . se) ;
for ( int i = 1 ; i <= n; i ++ ) cout << res[ i] ;
cout << endl;
}
signed main ( )
{
ios; int T; cin >> T;
while ( T -- ) solve ( ) ;
return 0 ;
}