10.13考试总结
10.13考试
1.送分题,\(O(n)\)处理前后缀,枚举断点,或者\(nlogn\)线段树暴力即可
code:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cstdlib>
#include<cctype>
using namespace std;
const int MAXX = 100010;
struct node
{
long long sum;
node(){
sum = 0;
}
}t[MAXX<<2];
long long a[MAXX],x,ans;
int n;
inline long long rd(){
long long x = 0;bool f = 0;
char c = getchar();
while(!isdigit(c)){
if(c == '-')f = 1;
c = getchar();
}
while(isdigit(c)){
x = (x << 1) + (x << 3) + (c ^ 48);
c = getchar();
}
return f ? -x : x;
}
inline void build(int cur,int l,int r){
if(l == r){
t[cur].sum = a[l];
return ;
}
int mid = (l + r) >> 1;
build(cur << 1,l,mid);
build(cur << 1 | 1,mid + 1,r);
t[cur].sum = t[cur<<1].sum | t[cur << 1 | 1].sum;
}
inline void update(int cur,int l,int r,int pos,long long val){
if(l==r){
t[cur].sum = val;
return ;
}
int mid = (l + r) >> 1;
if(pos <= mid)update(cur << 1,l,mid,pos,val);
if(pos > mid)update(cur << 1 | 1,mid + 1,r,pos,val);
t[cur].sum = t[cur<<1].sum | t[cur << 1 | 1].sum;
}
inline long long query(int cur,int l,int r,int L,int R){
if(L > R)return 0;
if(L <= l && r <= R)return t[cur].sum;
int mid = (l + r)>>1;
long long ans=0;
if(L <= mid) ans |= query(cur << 1,l,mid,L,R);
if(R > mid) ans |= query(cur << 1 | 1,mid + 1,r,L,R);
return ans;
}
int main(){
freopen("poker.in","r",stdin);
freopen("poker.out","w",stdout);
n = rd(); x = rd();
for(int i = 1;i <= n; ++i)a[i] = rd();
build(1,1,n);
for(int i = 1;i <= n; ++i){
update(1,1,n,i,a[i]*x);
long long now = (a[i]*x) | query(1,1,n,1,i - 1) | query(1,1,n,i + 1,n);
update(1,1,n,i,a[i]);
ans=max(ans,now);
}
printf("%lld",ans);
fclose(stdin);
fclose(stdout);
return 0;
}
2.根据\(a_i \times k \equiv x\pmod{n}\),导出\(gcd(a_i,n)|x\),我们枚举\(d|n\),如果\(gcd(a_i,n)|d\),那么所有的满足\(gcd(x,n)=d\),的x都能被走到
因为,d为x的约数,\(gcd(a_i,n)\)为d的约数,所以\(gcd(a_i,n)|x\),证毕
那么,\(gcd(x,n)=d\)转化为,\(gcd(\frac{x}{d},\frac{n}{d})=1\),即有\(\varphi(\frac{n}{d})\)个,这样不会重复,因为每一个数只会被他的最大公约数算到,所以不会重复
复杂度比较玄学:理论是\(O(n)\)
code:
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
int n,m,a[55],d[100000],cnt;
inline int gcd(int a,int b){
return b ? gcd(b,a % b) : a;
}
inline int phi(int x){
int ans = x;
for(int i = 2; i * i <= x;++i){
if(x % i == 0) {
ans = ans / i * (i - 1);
while(x % i == 0)x /= i;
}
}
if(x > 1)ans = ans / x * (x - 1);
return ans;
}
inline int solve(int x){
for(int i = 1;i <= m;++i)if(x % a[i] == 0)return phi(n / x);
return 0;
}
int main(){
freopen("running.in","r",stdin);
freopen("running.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i = 1 ;i <= m; ++i){
scanf("%d",&a[i]);
a[i] = gcd(a[i],n);
}
int num = 0;
for(int i = 1 ;i * i <= n;++i){
if(n % i == 0){
num += solve(i);
int x = n / i;
if(x != i)num += solve(x);
}
}
cout<< n - num<<endl;
return 0;
}