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;
}
posted @ 2018-10-13 21:59  ART_coder  阅读(51)  评论(0编辑  收藏  举报