【2020牛客NOIP賽前集訓營-提高組(第二場)】題解(GCD,包含,字首,移動)
阿新 • • 發佈:2020-10-21
目錄
最後加上沒有被計算的數的個數即可,因為這些數每個都只會貢獻\(1\)
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
先咕咕咕咕。。。