Day1
T1:
大意:一个850个点,8500条边的图,问所有点对之间的最小割有多少种不同的权值。至于为什么这就是所有的n-1种最小割...我也不太清楚。
T1贴一发别人的代码。。
//Copyright(c)2016 liuchenrui
#include
#define short unsigned short
#define inf 1000000000
using namespace std;
template
inline void splay(T &v){
v=0;char c=0;T p=1;
while(c<'0' || c>'9'){if(c=='-')p=-1;c=getchar();}
while(c>='0' && c<='9'){v=(v<<3)+(v<<1)+c-'0';c=getchar();}
v*=p;
}
struct Edge{
short to,next;int flow;
}edge[1000010];
short first[851],size;
short deep[851],dl[851];
void addedge(short x,short y,int z){
size++;
edge[size].to=y;
edge[size].next=first[x];
first[x]=size;
edge[size].flow=z;
}
void add(short x,short y,int z){
addedge(x,y,z),addedge(y,x,0);
}
short aim;
int dfs(short now,int flow){
if(now==aim)return flow;
int F=0;
for(short u=first[now];u&&flow;u=edge[u].next){
if(deep[edge[u].to]==deep[now]+1&&edge[u].flow){
int tmp=dfs(edge[u].to,min(flow,edge[u].flow));
F+=tmp;edge[u].flow-=tmp;edge[u^1].flow+=tmp;flow-=tmp;
}
}
if(!F)deep[now]=-5;
return F;
}
bool bfs(short S,short T){
memset(deep,0,sizeof(deep));
dl[1]=S;deep[S]=1;
short head=0,tail=1;
while(head!=tail){
head++;
for(int u=first[dl[head]];u;u=edge[u].next){
if(!deep[edge[u].to]&&edge[u].flow){
dl[++tail]=edge[u].to;
deep[edge[u].to]=deep[dl[head]]+1;
}
}
}
return deep[T];
}
int maxflow(short S,short T){
int ret=0;aim=T;
while(bfs(S,T)){
ret+=dfs(S,inf);
}
return ret;
}
short fr[8600],to[8600];
int fl[8600];
int ans[1000010];
short cnt,n,m,p[851];
void rebuild(){
memset(first,0,sizeof first);
size=1;
for(int k=1;k<=m;k++){
add(fr[k],to[k],fl[k]);
add(to[k],fr[k],fl[k]);
}
}
bool vis[860];
void dfs2(short now){
vis[now]=1;
for(int u=first[now];u;u=edge[u].next){
if(edge[u].flow&&!vis[edge[u].to]){
dfs2(edge[u].to);
}
}
}
void cdq_calc(short l,short r){
if(l>=r)return;
rebuild();
ans[++cnt]=maxflow(p[l],p[r]);
memset(vis,0,sizeof vis);
dfs2(p[l]);int t=l-1;
for(short i=l;i<=r;i++){
if(vis[p[i]]){
swap(p[i],p[++t]);
}
}
cdq_calc(l,t),cdq_calc(t+1,r);
}
int main(){
splay(n),splay(m);
for(short i=1;i<=m;i++){
splay(fr[i]),splay(to[i]),splay(fl[i]);
}
for(short i=1;i<=n;i++){
p[i]=i;
}
cdq_calc(1,n);
sort(ans+1,ans+cnt+1);
cnt=unique(ans+1,ans+cnt+1)-ans-1;
printf("%d\n",cnt);
//cerr<
首先YY了一个性质,对于两个凸包内的点a,b,一定有一个凸包上的点x使得max(ax,bx) > ab,有了这个性质我们就以知道,凸包内的一条边ab被访问,一定会在ax或者bx之后,而对于x点的最远点可以旋转卡壳得到。那么现在我们就定义凸包上的点是激活的,同时凸包内的点一开始是未激活的,一个点a被激活仅当ax是当前的最优解。比如现在的最优解是ax,我们令num[a]+1,num[x]+1,再求出a?的第num[a]+1大值,x?的num[x]+1大值,更新a和x的值,这个用堆维护就可以了。求第k大值也可以用堆维护(然而我并不会堆...强行线段树过之..),注意重点的情况,但是数据里好像没有(做凸包的时候注意一下就行了)...
#include
#include
#include
#include
#include
#include
#include
#include
#include
感觉没什么特别的..应该是人人都会的送分题那种....(为什么我写得那么长。。。。)
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
long long f[12][10][4][2][2],l,r;
int getnum(long long x) {
int ret = 0;
while(x > 0)
x /= 10,ret ++;
return ret;
}
long long get(int x) {
if(x == -1) return 0;
long long ret = 1;
for(int i = 1;i <= x;i ++)
ret = 1ll * ret * 10;
return ret;
}
long long Ask(long long x,int pos,int pre,int L,bool A,bool B) {
if(pos == 0) return 0;
if(A && B) return 0;
long long ret = 0;
int M = x / get(pos - 1);
if(pos == 11)
{
if(x < get(pos - 1)) return 0;
for(int i = 1;i <= M - 1;i ++)
ret += f[pos][i][3][0][0] + f[pos][i][3][0][1] + f[pos][i][3][1][0];
if(M == 4)
ret += Ask(x - M * get(pos - 1),pos - 1,M,1,1,B);
else if(M == 8)
ret += Ask(x - M * get(pos - 1),pos - 1,M,1,A,1);
else ret += Ask(x - M * get(pos - 1),pos - 1,M,1,A,B);
return ret;
}
if(pos == 1) M = M + 1;
if(L == 3)
{
if(A)
{
for(int i = 0;i <= M - 1;i ++)
if(i != 8)
{
ret += f[pos][i][1][0][0] + f[pos][i][1][1][0];
ret += f[pos][i][2][0][0] + f[pos][i][2][1][0];
ret += f[pos][i][3][0][0] + f[pos][i][3][1][0];
}
}
else if(B)
{
for(int i = 0;i <= M - 1;i ++)
if(i != 4)
{
ret += f[pos][i][1][0][0] + f[pos][i][1][0][1];
ret += f[pos][i][2][0][0] + f[pos][i][2][0][1];
ret += f[pos][i][3][0][0] + f[pos][i][3][0][1];
}
}
else
{
for(int i = 0;i <= M - 1;i ++)
{
ret += f[pos][i][1][0][0] + f[pos][i][1][1][0] + f[pos][i][1][0][1];
ret += f[pos][i][2][0][0] + f[pos][i][2][1][0] + f[pos][i][2][0][1];
ret += f[pos][i][3][0][0] + f[pos][i][3][1][0] + f[pos][i][3][0][1];
}
}
}
else
{
if(A)
{
for(int i = 0;i <= M - 1;i ++)
if(i != 8)
{
if(i == pre)
for(int j = 3;j >= 3 - L;j --)
ret += f[pos][i][j][0][0] + f[pos][i][j][1][0];
else ret += f[pos][i][3][0][0] + f[pos][i][3][1][0];
}
}
else if(B)
{
for(int i = 0;i <= M - 1;i ++)
if(i != 4)
{
if(i == pre)
for(int j = 3;j >= 3 - L;j --)
ret += f[pos][i][j][0][0] + f[pos][i][j][0][1];
else ret += f[pos][i][3][0][0] + f[pos][i][3][0][1];
}
}
else
{
for(int i = 0;i <= M - 1;i ++)
{
if(i == pre)
for(int j = 3;j >= 3 - L;j --)
ret += f[pos][i][j][0][0] + f[pos][i][j][1][0] + f[pos][i][j][0][1];
else ret += f[pos][i][3][0][0] + f[pos][i][3][1][0] + f[pos][i][3][0][1];
}
}
}
x = x - 1ll * M * get(pos - 1);
if(M == pre)
ret += Ask(x,pos - 1,M,min(L + 1,3),(M == 4 || A),(M == 8 || B));
else if(L == 3) ret += Ask(x,pos - 1,M,3,(M == 4 || A),(M == 8 || B));
else ret += Ask(x,pos - 1,M,1,(M == 4 || A),(M == 8 || B));
return ret;
}
void pre_work() {
f[1][0][1][0][0] = 1;
f[1][1][1][0][0] = 1;
f[1][2][1][0][0] = 1;
f[1][3][1][0][0] = 1;
f[1][4][1][1][0] = 1;
f[1][5][1][0][0] = 1;
f[1][6][1][0][0] = 1;
f[1][7][1][0][0] = 1;
f[1][8][1][0][1] = 1;
f[1][9][1][0][0] = 1;
for(int i = 2;i <= 11;i ++)
for(int j = 0;j <= 9;j ++)
for(int w = 0;w <= 9;w ++)
for(int k = 1;k <= 3;k ++)
for(int g = 0;g <= 1;g ++)
for(int h = 0;h <= 1;h ++)
{
if(j == 4)
{
if(k == 3) f[i][j][3][1][h] += f[i - 1][w][3][g][h];
else if(j == w) f[i][j][min(k + 1,3)][1][h] += f[i - 1][w][k][g][h];
else f[i][j][1][1][h] += f[i - 1][w][k][g][h];
}
else if(j == 8)
{
if(k == 3) f[i][j][3][g][1] += f[i - 1][w][3][g][h];
else if(j == w) f[i][j][min(k + 1,3)][g][1] += f[i - 1][w][k][g][h];
else f[i][j][1][g][1] += f[i - 1][w][k][g][h];
}
else {
if(k == 3) f[i][j][3][g][h] += f[i - 1][w][3][g][h];
else if(j == w) f[i][j][min(k + 1,3)][g][h] += f[i - 1][w][k][g][h];
else f[i][j][1][g][h] += f[i - 1][w][k][g][h];
}
}
}
int main() {
cin>>l>>r;
pre_work();
cout<
Day2
T1:题意感觉有点绕。。搞清楚已知条件之后发现就是一个大质数分解+一个拓展欧几里锝。直接上pollard rho即可。
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
long long E,N,c,p = 0,q,k,r,A,n,B;
long long ksc(long long x,long long y) {
long long ret = 0;
while(y > 0) {
if(y % 2 == 1) ret = (ret + x) % N;
x = (x + x) % N;
y = y / 2;
}
return ret;
}
long long f(long long x) {return (1ll * ksc(x,x) + 1ll * k) % N;}
long long gcd(long long x,long long y) {
if(y == 0) return x;
return gcd(y,x % y);
}
long long find(long long x) {
k = 1ll * ((rand() * rand() % N) * (rand() * rand() % N)) % N;
long long a = f(1);
long long b = f(f(1));
while(a != b)
{
long long y = abs(a - b);
if(gcd(y,x) != 1) return gcd(x,y);
a = f(a);
b = f(f(b));
}
return 0;
}
void work(long long x) {
p = find(x);
while(p == 0)
p = find(x);
q = x / p;
}
long long exgcd(long long x,long long y) {
if(y == 0) {A = 1;B = 0;return x;}
long long ret = exgcd(y,x % y);
long long t = A;
A = B;
B = t - (x / y) * B;
return ret;
}
long long ksm(long long x,long long y) {
long long ret = 1;
while(y > 0) {
if(y % 2 == 1) ret = ksc(ret,x);
x = ksc(x,x);
y = y / 2;
}
return ret;
}
int main() {
srand(127);
cin>>E>>N>>c;
work(N);
r = (p - 1ll) * (q - 1ll);
long long C = exgcd(E,r);
long long t = r / C;
A = ((A * (1 / C)) % t + t) % t;
n = ksm(c,A);
cout<
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
int son[32000010][2],len,A[10],n,tot = 0,tim[32000010],cnt,s[50],q[100];
int getint() {
int ret = 0;
char g = 'd';
while(g < '0' || g > '9') g = getchar();
while(g >= '0' && g <= '9') ret = ret * 10 + g - '0',g = getchar();
return ret;
}
void insert(int x) {
int Now = 0;
for(int i = 1;i <= len;i ++)
{
int t = s[i] - 0;
if(son[Now][t] == 0)
{
son[Now][t] = ++ tot;
Now = tot;
}
else Now = son[Now][t];
}
if(tim[Now] == 0) tim[Now] = x;
}
int Ask() {
int ret = 0;
int Now = 0;
int tail = 0;
for(int i = 1;i <= len;i ++)
{
int t = s[i] - 0;
Now = son[Now][t];
if(Now == 0) break;
if(tim[Now] != 0)
{
while(tail && tim[q[tail]] > tim[Now]) tail --;
q[ ++tail] = Now;
}
}
for(int i = 1;i <= tail;i ++)
if(tim[q[i]] >= A[5] && tim[q[i]] <= A[6])
ret ++;
return ret;
}
int main() {
scanf("%d",&n);
for(int i = 1;i <= n;i ++)
{
char c = 'd';
while(c != 'A' && c != 'Q') c = getchar();
if(c == 'A')
{
for(int j = 1;j <= 5;j ++)
A[j] = getint();
for(int j = 1;j <= 4;j ++)
for(int k = 8;k >= 1;k --)
if(A[j] >= (1 << (k - 1)))
s[(j - 1) * 8 + (8 - k + 1)] = 1,A[j] -= (1 << (k - 1));
else s[(j - 1) * 8 + (8 - k + 1)] = 0;
len = min(32,A[5]);
insert( ++cnt);
}
else
{
for(int j = 1;j <= 6;j ++)
A[j] = getint();
for(int j = 1;j <= 4;j ++)
for(int k = 8;k >= 1;k --)
if(A[j] >= (1 << (k - 1)))
s[(j - 1) * 8 + (8 - k + 1)] = 1,A[j] -= (1 << (k - 1));
else s[(j - 1) * 8 + (8 - k + 1)] = 0;
len = 32;
printf("%d\n",Ask());
}
}
return 0;
}
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
long long n,k;
int p[100],tot = 0;
bool visit[200];
struct cp {
long long val;int x,y,z;
cp(){}
cp(long long _v,int _x,int _y,int _z){val = _v,x = _x,y = _y,z = _z;}
bool operator < (const cp &b)const{return val < b.val;}
};
priority_queue Q;
int main() {
//freopen("lx.in","r",stdin);
//freopen("lx.out","w",stdout);
cin>>n>>k;
for(int i = 2;i <= 128;i ++)
{
if(visit[i] == false) p[ ++tot] = i;
for(int j = 1;j <= tot && p[j] * i <= 128;j ++)
{
visit[i * p[j]] = true;
if(i % p[j] == 0) break;
}
}
for(int i = 1;i <= tot;i ++)
{
long long x = 1;
for(int j = 1;x <= n / p[i];j ++)
Q.push(cp(1ll * x * p[i],j,i - 1,i)),x = 1ll * x * p[i];
}
for(int i = 1;i <= k - 1;i ++)
{
cp t = Q.top();
Q.pop();
if(t.x != 1)
for(int j = t.y;j >= 1;j --)
Q.push(cp(1ll * t.val / p[t.z] * p[j],t.x - 1,j,t.z));
}
cp t = Q.top();
cout<