1. 程式人生 > 實用技巧 >【2020牛客NOIP賽前集訓營-提高組(第二場)】題解(GCD,包含,字首,移動)

【2020牛客NOIP賽前集訓營-提高組(第二場)】題解(GCD,包含,字首,移動)

目錄

T1:GCD

title

solution

非常水,看一眼就知道了
首先我們知道每一個數都有唯一的標準整數分解,即拆成若干個質數的冪的乘積
而我們又知道質數彼此互質,\(gcd()=1\)
所以就可以迅速反應到,如果一個數有\(\ge 2\)個質數因子,那麼\(gcd\)一定等於\(1\)
否則\(gcd\)就是唯一的質數因子
這樣的話,需要尋找的特殊數一定是冪級遞增

尤拉篩出\(n\)以內的所有質數,然後進行冪級累乘,時間複雜度就是\(O(nlogn)\)


最後加上沒有被計算的數的個數即可,因為這些數每個都只會貢獻\(1\)

然後直接幹掉這道水題

code

#include <cstdio>
#define ll long long
#define MAXN 10000000
int a, b, cnt;
int prime[MAXN + 5];
bool vis[MAXN + 5];
ll ans[MAXN + 5];

void sieve() {
	for( int i = 2;i <= MAXN;i ++ ) {
		if( ! vis[i] )
			vis[i] = 1, prime[++ cnt] = i;
		for( int j = 1;i * prime[j] <= MAXN && j <= cnt;j ++ ) {
			vis[i * prime[j]] = 1;
			if( i % prime[j] == 0 ) break;
		}
	}
}

int main() {
	sieve();
	for( int i = 1;i <= MAXN;i ++ )
		ans[i] = 1;
	for( int i = 1;i <= cnt;i ++ ) {
		int j = 1;
		while( 1ll * j * prime[i] <= MAXN ) {
			j *= prime[i];
			ans[j] = prime[i];
		}
	}
	for( int i = 1;i <= MAXN;i ++ )
		ans[i] += ans[i - 1];
	scanf( "%d %d", &a, &b );
	printf( "%lld\n", ans[b] - ans[a - 1] );
	return 0;
}

T2:包含

title

solution

這道題只要瞭解一點點列舉子集就能\(AC\)

for( int i = S;i;i = ( i - 1 ) & S )

每次隨便丟掉至少\(1\)\(1\),所以一個數列舉子集的時間複雜度是\(O(logn)\)
\(n\)個數,這道題時間複雜度就是\(O(nlogn)\)

自測大資料跑了1.3s以為會T,但是沒想到交上去能跑過誒

code

#include <cstdio>
#include <iostream>
using namespace std;
#define MAXN 100005
#define MAXM 1000000
int n, m, cnt, maxx;
int a[MAXN];
bool vis[MAXM + 5];

int main() {
	scanf( "%d %d", &n, &m );
	for( int i = 1;i <= n;i ++ ) {
		scanf( "%d", &a[i] );
		maxx = max( maxx, a[i] );
	}
	for( int i = 1;i <= n;i ++ ) {
		int x = a[i];
		if( vis[x] ) continue;
		vis[x] = 1, cnt ++;
		if( cnt == maxx ) continue;
		for( int j = x;j;j = ( ( j - 1 ) & x ) )
			if( ! vis[j] ) {
				vis[j] = 1;
				cnt ++;
				if( cnt == maxx ) break;
			}
	}
	for( int i = 1, x;i <= m;i ++ ) {
		scanf( "%d", &x );
		if( vis[x] ) printf( "yes\n" );
		else printf( "no\n" );
	}
	return 0;
}

T3:字首

title

solution

大模擬!!無需多說慢慢敲,高精直接上

code

#include <cstdio>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define int long long
#define mod 998244353
#define MAXN 100005
vector < int > pos[30];
char s[MAXN], t[MAXN];
int pi[MAXN][2], num[MAXN];
int n, ans;

int calc( int l, int r, int siz, int len ) {
	int cnt = 0, ip;
	for( int i = l;i <= r;i ++ )
		num[i - l + 1] = t[i] ^ 48;
	for( ip = r - l + 1;! num[ip];ip -- );
	num[ip] --;
	for( int i = ip + 1;i <= r - l + 1;i ++ )
		num[i] = 9;
	int g = 0, R = 0;
	for( int i = 1;i <= r - l + 1;i ++ )
		g = R * 10 + num[i], num[++ cnt] = g / siz, R = g % siz;
	g = 0;
	for( int i = cnt;i;i -- )
		g += len * num[i], num[i] = g % 10, g /= 10;
	for( int i = 1;i <= cnt;i ++ )
		g = ( g * 10 + num[i] ) % mod;
	ans = ( ans + g ) % mod;
	return R;
}

signed main() {
	scanf( "%s", s );
	int lens = strlen( s );
	for( int i = 0;i < lens;i ++ )
		pos[s[i] ^ 96].push_back( i ), pi[i][0] = pos[s[i] ^ 96].size() - 1;
	for( int i = 0;i < lens;i ++ )
		pos[0].push_back( i ), pi[i][1] = i;
	scanf( "%lld", &n );
	while( n -- ) {
		ans = 0;
		scanf( "%s", t );
		int lent = strlen( t );
		int l = 0, r = 0, now = lens - 1, nxt, flag = 1, f;
		for( ;l < lent;l = ++ r ) {
			if( t[l] == '*' ) t[l] = 96, f = 1;
			else f = 0;
			int id = t[l] ^ 96, siz = pos[id].size();
			if( ! siz ) { flag = 0; break; }
			if( pos[id][siz - 1] <= now ) nxt = pos[id][0];
			else nxt = *upper_bound( pos[id].begin(), pos[id].end(), now );
			if( now < nxt ) ans = ( ans + nxt - now ) % mod, now = nxt;
			else ans = ( ans + lens + nxt - now ) % mod, now = nxt;
			if( l + 1 < lent && isdigit( t[l + 1] ) )
				for( ;r + 1 < lent && isdigit( t[r + 1] );r ++ );
			if( l < r ) {
				int R = calc( l + 1, r, siz, lens );
				if( R ) {
					nxt = pos[id][( pi[now][f] + R ) % siz];
					if( now < nxt ) ans = ( ans + nxt - now ) % mod, now = nxt;
					else ans = ( ans + lens + nxt - now ) % mod, now = nxt;
				}
			}
		}
		if( ! flag ) printf( "-1\n" );
		else printf( "%lld\n", ans );
	}
	return 0;
}

T4:移動

title

先咕咕咕咕。。。