NOIP2014提高组第二试题解

本题通过枚举和数论优化方法解决无线问题。对于函数f(x),当f(x) mod p = 0时,x可能是解。若不等于0,可以通过枚举0~P-1排除非解,并利用多个p过滤,找到可能的答案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

第一题 wireless 枚举即可,如果数据变大可用部分和优化

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
using namespace std;
const int maxn = 600;
int d, n,w[maxn][maxn],x,y,z;
int cnt = 0, ans = 0;
int get(int x, int y)
{
	int sum = 0;
	for(int i = x-d; i <= x+d; ++i)
		for(int j = y-d; j <= y+d; ++j)
            if (i >=0 && j >=0)
			   sum += w[i][j];
	return sum;
}
int main() {
	freopen("wireless.in", "r", stdin);
	freopen("wireless.out", "w", stdout);
	scanf("%d%d", &d, &n);
	for(int i = 1; i <= n; i++){
		cin>>x>>y>>z;
		w[x][y] = z;
	}
	for(int i = 0; i <= 128; i++)
        for(int j = 0; j <= 128; j++) {
			int x = get(i, j);
			if(x > ans) {
				ans = x; 
                cnt = 1;
            } else if(x == ans)
			    cnt++;
	}
	printf("%d %d\n", cnt, ans);
	return 0;
}

第二题:寻找道路,这道题感觉和NOIP2008的最优贸易类似,求最短路,只不过多了一点限制,那么我们先把满足要求的点找出来,在满足要求的点的新图上求个最短路即可。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include<queue>
using namespace std;
#define maxn 600000
struct Edge {
	int v,next;
}e[maxn];
int first[maxn],d[maxn],u1[maxn], u2[maxn],en;
bool mark[maxn];
int n, m;
int s, t;
void add(int u, int v) {
	en++;
	e[en].v = v;
	e[en].next = first[u];
	first[u] = en;
}
void bfs(int u, int flag) {
	memset(d, -1, sizeof(d));
	queue<int> q;
	q.push(u);
	d[u] = 0;
	while(!q.empty()) {
		int x = q.front();
		q.pop();
		for(int j = first[x]; j > 0; j = e[j].next)
		if (j % 2 == flag && !mark[e[j].v]) {
			int v = e[j].v;
			if(d[v] == -1) {
				d[v] = d[x] + 1;
				q.push(v);
			}
		}
	}
	return ;
}
int main() {
	freopen("road.in", "r", stdin);
	freopen("road.out", "w", stdout);
	memset(first, -1, sizeof(first));
	scanf("%d%d", &n, &m);
    en = 0; 
	for(int i = 1; i <= m; i++) {
		scanf("%d%d", &u1[i], &u2[i]);
		add(u1[i],u2[i]);
        add(u2[i],u1[i]);
    }
	scanf("%d%d", &s, &t);
	bfs(t, 0);
	for(int i = 1; i <= m; i++)
		if(d[u2[i]] == -1)
			mark[u1[i]] = true;
	bfs(s, 1);
	printf("%d\n", d[t]);
	return 0;
}


第三题:解方程,一看数据好大,因为高次方程没有解的方法,所以1~m只能枚举,但是ai是高精度数,但是我们可以mod一个数,因为写高精度没有必要

f(x)  = anx^n +...+a0

如果f(x) mod p = 0    x非常有可能是解,这样就不用写高精度了,70分

然后f(x) mod p != 0 那么f(x + Np)  = f(x) != 0  那么实际上我们没有必要枚举1~M  因为我们可以枚举0~P-1,然后推测出p~M这些数哪些一定不是答案。

多找几个p把不是答案的剔除,剩下的基本上就是解了。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std;
#define maxn 1000010
const int prime[] = {10007,10917,30071};
int n,m;
long long a[110][5];
bool f[100000][5];
int cnt[maxn];
char s[10010];
bool calc(int value, int j) {
    long long tmp = 0;
    for (int i = n; i>=0; --i)
        tmp = (tmp * value + a[i][j]) % prime[j];
    return tmp != 0;
}
int main(){
    freopen("equation.in", "r", stdin);
	freopen("equation.out", "w", stdout);
    cin>>n>>m;
    for (int i = 0; i <= n; ++i) {
        scanf("%s", s);
        int len = strlen(s);
        int sign = 1;
        for (int l = 0; l < len; ++l) {
            if(s[l]=='-')
               sign = -1;
            else
                for (int j = 0; j < 3; ++j)
                    a[i][j]=( a[i][j] * 10 + s[l]-'0' ) % prime[j];
        }
        if (sign == -1)
           for (int j = 0; j < 3; ++j)
               a[i][j] = prime[j] - a[i][j];
    }
     
    for (int j = 0; j < 3; ++j)
        for(int i = 0; i < prime[j]; ++i)
            f[i][j]=calc(i,j);
         
    for (int i = 1; i <=m; ++i) {
        bool flag = true;
        for(int j = 0; j < 3; ++j)
            if(f[i % prime[j]][j]) {
                flag = false; break;
            }
        if(flag)
            cnt[++cnt[0]] = i;
    }
    printf("%d\n", cnt[0]);
    for (int i = 1; i <= cnt[0]; ++i)
        printf("%d\n",cnt[i]);
    return 0;
}



评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值