3道noip提高真题.
得分:280.
t1:同余方程
noip2012 day2 t1.
题意:求关于x的同余方程 a x (equiv) 1 (pmod {b}) 的最小正整数解, 数据保证一定有解。
思路:(exgcd)[暴力]
[正解]其实就是求不定方程ax-by=1的解,因为数据保证一定有解,所以gcd(a, b) = 1, 用扩欧求出x后再调解使之在1~b之间即可。
Code:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cmath>
#include <vector>
using namespace std;
//Mystery_Sky
//
#define INF 0x3f3f3f3f
#define ll long long
#define M 1000100
inline ll read()
{
ll 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*10+c-'0';c=getchar();}
return x*f;
}
ll a, b;
ll x, y, t;
void exgcd(ll a, ll b, ll &t, ll &x, ll &y)
{
if(!b) {t = a; x = 1; y = 0;}
else {exgcd(b, a%b, t, y, x); y -= x * (a / b);}
}
int main() {
a = read(), b = read();
exgcd(a, b, t, x, y);
printf("%lld
", (x + b) % b);
return 0;
}
t2:信息传递
noip2015 day1 t2
题意:n个同学之间互相传递信息,每个人只能将自己知道的信息传递给自己唯一的信息传递对象,初始时每人只知道自己的生日信息,每轮游戏中每个人会将自己之前得到的信息传递给自己的传递对象,当有人从别人那里得到自己的生日信息时,游戏结束。问游戏最多能进行几轮。
思路:(tarjan算法)以同学为点,信息传递给传递对象为边建一个有向图,只需找到图上最小的环即可,输出这个环的大小。这里用的tarjan去找环。
(这题用冰茶姬应该也能做)
Code:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <stack>
#include <cstring>
#include <algorithm>
using namespace std;
#define MAXN 200010
#define INF 0x3f3f3f3f
int head[MAXN], cnt, ans;
int m, n, sum, dfn[MAXN], low[MAXN];
bool visit[MAXN];
int sumscc, scc[MAXN];
stack <int> s;
struct Edge{
int to, next;
}edge[MAXN];
inline void add(int u, int v)
{
edge[cnt].to = v;
edge[cnt].next = head[u];
head[u] = cnt++;
}
void tarjan(int u)
{
dfn[u] = low[u] = ++sum;
s.push(u);
visit[u] = true;
for(int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].to;
if(!dfn[v]) {
tarjan(v);
low[u] = min(low[u], low[v]);
}
else if(visit[v]) low[u] = min(low[u], dfn[v]);
}
if(low[u] == dfn[u]) {
int j, cnt = 0;
do{
j = s.top();
s.pop();
visit[j] = false;
cnt++;
}while(j != u);
if(cnt != 1) ans = min(ans, cnt);
}
}
int main() {
scanf("%d", &n);
int x;
memset(head, -1, sizeof(head));
for(int i = 1; i <= n; i++) {
scanf("%d", &x);
add(i, x);
}
ans = INF;
for(int i = 1; i <= n; i++)
if(!dfn[i]) tarjan(i);
printf("%d
", ans);
return 0;
}
t3:靶形数独
noip2009 t4
题意:给一个正常数独的每个格子上增加一个分值,越靠近中心分数越高。对于一个数独,总分数为完成时每个格子上所填入的数字与格子的分值的乘积的总和。输出给定靶形数独的最高分数
思路:(搜索+剪枝)
[暴力]