首先直接上一个最大流模板
然后在n<=1000的范围内打表(这题一定是有规律的为什么呢?因为是从小到大而且是只能是小连接大,而且有事1-n-1条件本身规律性就很强。)
然后我们注意到由于是异或运算首先考虑的是和2^k的关系,也就是说存在的规律应该是和2^k的相关。
然后一般打表就打出各项的差值和真正值就好了,观察下发现
2 5 2 三个数是成周期性变化的,然后每隔4个数会成一次突变,嗯如果这你表打小了的话规律就是这样了。但是当n=1000的时候发现在n=2^k的时候有会呈现一个不同的突变
所以有三种规律:对于差值:从第6项开始
1. 2 5 2呈现周期性变化。
2.如果一个n=2^k*乘上一个奇数 那么他的差值是f(2^k)+1的 f是一个映射f(x)=x^2+1
3.如果一个n恰好等于2^k的时候差值是 g(2^k)+1的 g又是一个映射具体规律看表.
这样我们阔以先预处理出f和g
然后看n的二进制上有多少个1消灭第3个规律
然后n/4消灭第一个规律
然后n每次除二看奇数有多少个消灭第二个规律
总的复杂度是log(n)的。
打表代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
const int INF = 1e9;
const int maxn = 1e3 + 5;
const int maxv = 1e6 + 7;
int head[maxv], cur[maxv], d[maxv], s, t, k, sum;
int n, m, dis[maxn];
struct node
{
int v, w, next;
}edge[maxv];
void addEdge(int u, int v, int w)
{
edge[k].v = v;
edge[k].w = w;
edge[k].next = head[u];
head[u] = k++;
edge[k].v = u;
edge[k].w = 0;
edge[k].next = head[v];
head[v] = k++;
}
int bfs()
{
memset(d, 0, sizeof(d));
d[s] = 1;
queue<int> q;
q.push(s);
while (!q.empty())
{
int u = q.front();
if (u == t) return 1;
q.pop();
for (int i = head[u]; i != -1; i = edge[i].next)
{
int to = edge[i].v, w = edge[i].w;
if (w && d[to] == 0)
{
d[to] = d[u] + 1;
if (to == t) return 1;
q.push(to);
}
}
}
return 0;
}
int dfs(int u, int maxflow)
{
if (u == t) return maxflow;
int ret = 0;
for (int i = cur[u]; i != -1; i = edge[i].next)
{
int to = edge[i].v, w = edge[i].w;
if (w && d[to] == d[u] + 1)
{
int f = dfs(to, min(maxflow - ret, w));
edge[i].w -= f;
edge[i ^ 1].w += f;
ret += f;
if (ret == maxflow) return ret;
}
}
return ret;
}
int Dinic()
{
int ans = 0;
while (bfs() == 1)
{
memcpy(cur, head, sizeof(head));
ans += dfs(s, INF);
}
return ans;
}
int main(void)
{
int e;
while (~scanf("%d", &e))
{
int pre = 0;
for (int i = 2; i <= e; i++)
{
n = i;
memset(head, -1, sizeof(head));
s = 0, t = n - 1; k = 0, sum = 0;
for (int i = 0; i < n; i++)
{
for (int j = i + 1; j < n; j++)
{
if (j == n - 1) dis[i] = i ^ j, sum += i ^ j;
addEdge(i, j, i^j);
}
}
int cur = Dinic();
printf("%2d: %3d 差值:%3d\n", i, cur, cur - pre);
pre = cur;
}
}
return 0;
}