提高组都是神仙打架%%%
T1:
对于每个素数i,显然f[i] = i.
那么根据唯一分解定理,对于每个合数i,如果它分解后,有多个素因子,那么显然为1.
否组就是最小的素因子。
那么,我们可以在线性筛中处理即可。
线性筛,其实就是利用素数和一个和当前素数肯定有不同素因子的数乘积来筛合数的过程。
那么,在判断中,当这个数首先要满足只有一个素因子,那么在满足i % prime[j]时,显然筛出的合数只有一个素因子prime[j].
#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<double,int> pii; const int N = 1e7+5; const int M = 1e6+5; const LL Mod = 1e9+7; //#define rg register #define pi acos(-1) #define INF 1e18 #define CT0 cin.tie(0),cout.tie(0) #define IO ios::sync_with_stdio(false) #define dbg(ax) cout << "now this num is " << ax << endl; namespace FASTIO{ inline int read() { int x = 0,f = 1;char c = getchar(); while(c < '0' || c > '9'){if(c == '-')f = -1;c = getchar();} while(c >= '0' && c <= '9'){x = (x << 1) + (x << 3) + (c ^ 48);c = getchar();} return x * f; } void print(int x){ if(x < 0){x = -x;putchar('-');} if(x > 9) print(x/10); putchar(x%10+'0'); } } using namespace FASTIO; bool vis[N]; int prime[N],tot = 0,f[N]; void init() { for(int i = 2;i < N;++i) { if(!vis[i]) { prime[++tot] = i; f[i] = i; } for(int j = 1;j <= tot && prime[j] * i < N;++j) { vis[i * prime[j]] = 1; f[i * prime[j]] = 1; if(i % prime[j] == 0 && f[i] != 1) f[i * prime[j]] = prime[j]; if(i % prime[j] == 0) break; } } } int main() { init(); int a,b;a = read(),b = read(); LL ans = 0; for(int i = a;i <= b;++i) ans += f[i]; printf("%lld ",ans); system("pause"); return 0; }
T2:
做法好像蛮多的。
dp[i]表示是否能得到。
显然输入的值可以&自己得到。
且可以发现,对于可以得到的每个数x,去除它的二进制上任意个为1的数,变成的那个数都可以&x来得到那个数。
所以我们可以枚举每个数然后枚举去除几个0然后再去更新dp。
但是其实并没有必要枚举几个0.
我们倒着按值域dp,每次都去除每个位上的一个0,可以发现,因为是倒着枚举值域,所以最后所有数都会被包括在里面。(和枚举几个0等效
#include<bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<double,int> pii; const int N = 1e6+5; const int M = 1e6+5; const LL Mod = 1e9+7; //#define rg register #define pi acos(-1) #define INF 1e18 #define CT0 cin.tie(0),cout.tie(0) #define IO ios::sync_with_stdio(false) #define dbg(ax) cout << "now this num is " << ax << endl; namespace FASTIO{ inline int read() { int x = 0,f = 1;char c = getchar(); while(c < '0' || c > '9'){if(c == '-')f = -1;c = getchar();} while(c >= '0' && c <= '9'){x = (x << 1) + (x << 3) + (c ^ 48);c = getchar();} return x * f; } void print(int x){ if(x < 0){x = -x;putchar('-');} if(x > 9) print(x/10); putchar(x%10+'0'); } } using namespace FASTIO; int dp[N],a[N]; int main() { int n,m;n = read(),m = read(); for(int i = 1;i <= n;++i) a[i] = read(),dp[a[i]] = 1; for(int i = N - 1;i >= 0;--i) { for(int j = 0;(1 << j) <= i;++j) { if(dp[i] && (i >> j) & 1) dp[i - (1 << j)] = 1; } } while(m--) { int x;x = read(); printf("%s ",dp[x] == 1 ? "yes" : "no"); } system("pause"); return 0; }