杂题
NOI2013
很有奥妙的题。暴力分很多,直接枚举有60,加个random_shuflle优化一下就有70了。
把n个向量写在一起变成一个n*d的矩阵,这个矩阵乘它的转置得到的矩阵第i行第j列就是第i个向量和第j个向量的内积,把这个矩阵跟全1矩阵比较即可知道有无解。
这样是个暴力的复杂度,用一些玄学的方式优化一下,随机一个n维向量和两个矩阵相乘,再比较。为了提高正确性要多随机几次。
这是mod2的情况下,mod3的情况下因为结果为0,1,2不能和全1矩阵比较,发现2^2=1^2=1(mod 3),那么把结果平方再比较。化化式子发现相当于每个向量变成d^2维的向量,bi*j=ai*aj。
暴力十进制矩阵快速幂,卡卡常说不定就过了。
更优美的做法,大力推一波式子,加等比数列求和加欧拉定理加快速幂就差不多了。
thupc2018
太菜了网络赛只写了几道签到题,签到题都不会写没写完,要是以后改了再来补。
一直想写没写的几道题:
2961: 共点圆
cdq维护凸包,也是当时觉得好难啊。其实蛮好写的。至少比splay好写多了,但若是要强制在线我也没什么办法啊。
001_d
读题读了好久,好久,好久。。。
相同的位置连边,要使得最后图联通,画图发现奇数的回文串只能伸出去一边,偶数的可以伸出去两边或一边,奇数的只能放两端,偶数的可以放中间或两端。
001_e
$ans=\sum_{i=1}^n\sum_{j=1}^{i-1}C(a_j+a_i+b_j+b_i,a_j+a_i)$
即网格图上从$(-a_i,-b-i)$,到$(a_j,b_j)$的方案数
把所有i一起dp,减去从i到i的再除以2即可。
001_f
长沙做过的原题我都不会,,真真是菜得没话说。。
原序列为a,设p[a[i]]=i,问题转换为使p数组字典序最小。操作转换为相邻两项的值的差的绝对值大于k即可交换。每个数向它后面不能交换的连边,即它们的先后顺序定下来了,再拓扑排序即可。发现这样会有多余的边。每个数只会向(a-k,a),(a,a+k),线段树维护区间位置最小值,每个数向后面第一个不能交换的连边即可。
002_d
sxy出过的题,似乎被我暴力搞过了。传送门
002_e
我根本一点都不懂博弈啊。
llj说因为子游戏之间有影响所以不能直接用nim积算sg函数。
题解好奥妙啊。这个博主写得草鸡好啊,图画的简直良心。
1 //Achen 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 #include<cstdlib> 6 #include<vector> 7 #include<cstdio> 8 #include<queue> 9 #include<cmath> 10 #include<set> 11 #include<map> 12 #define For(i,a,b) for(int i=(a);i<=(b);i++) 13 #define Rep(i,a,b) for(int i=(a);i>=(b);i--) 14 const int N=1e5+7; 15 typedef long long LL; 16 typedef double db; 17 using namespace std; 18 int n,a[N],fl1,fl2,sum; 19 20 template<typename T> void read(T &x) { 21 char ch=getchar(); x=0; T f=1; 22 while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar(); 23 if(ch=='-') f=-1,ch=getchar(); 24 for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f; 25 } 26 27 bool cmp(const int &A,const int &B) { 28 return A>B; 29 } 30 31 //#define DEBUG 32 int main() { 33 #ifdef DEBUG 34 freopen("1.in","r",stdin); 35 //freopen(".out","w",stdout); 36 #endif 37 read(n); 38 For(i,1,n) read(a[i]); 39 sort(a+1,a+n+1,cmp); 40 For(i,1,n) { 41 if(a[i+1]<i+1) { 42 i--; 43 int j=i; while(a[j+1]>i) j++; 44 if(((a[i+1]-i)&1)&&((j-i)&1)) puts("Second"); 45 else puts("First"); 46 break; 47 } 48 } 49 return 0; 50 }
002_f
这题就更加奥妙重重了。。还是刚才那个博主,写得特别好。
1 //Achen 2 #include<algorithm> 3 #include<iostream> 4 #include<cstring> 5 #include<cstdlib> 6 #include<vector> 7 #include<cstdio> 8 #include<queue> 9 #include<cmath> 10 #include<set> 11 #include<map> 12 #define For(i,a,b) for(int i=(a);i<=(b);i++) 13 #define Rep(i,a,b) for(int i=(a);i>=(b);i--) 14 const int N=2007,mod=1e9+7; 15 typedef long long LL; 16 typedef double db; 17 using namespace std; 18 int n,k; 19 LL dp[N][N],fac[N*N],inv[N*N]; 20 21 template<typename T> void read(T &x) { 22 char ch=getchar(); x=0; T f=1; 23 while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar(); 24 if(ch=='-') f=-1,ch=getchar(); 25 for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f; 26 } 27 28 LL C(int n,int m) { 29 if(n<m) return 0; 30 return fac[n]*inv[m]%mod*inv[n-m]%mod; 31 } 32 33 //#define DEBUG 34 int main() { 35 #ifdef DEBUG 36 freopen("1.in","r",stdin); 37 //freopen(".out","w",stdout); 38 #endif 39 read(n); read(k); 40 fac[0]=inv[0]=inv[1]=1; 41 For(i,1,n*k) fac[i]=fac[i-1]*i%mod; 42 For(i,2,n*k) inv[i]=(mod-mod/i*inv[mod%i]%mod)%mod; 43 For(i,2,n*k) inv[i]=inv[i-1]*inv[i]%mod; 44 if(k==1) { 45 puts("1"); 46 return 0; 47 } 48 dp[n][n]=1; 49 Rep(i,n,0) { 50 Rep(j,n,i) { 51 if(i) 52 (dp[i-1][j]+=dp[i][j])%=mod; 53 if(j>i) 54 (dp[i][j-1]+=dp[i][j]*(k>2?C(i+j*(k-1)-1,k-2):1)%mod)%=mod; 55 } 56 } 57 LL ans=dp[0][0]*fac[n]%mod; 58 printf("%lld\n",ans); 59 return 0; 60 }
003_d
//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<queue>
#include<cmath>
#include<set>
#include<map>
#define For(i,a,b) for(int i=(a);i<=(b);i++)
#define Rep(i,a,b) for(int i=(a);i>=(b);i--)
const int N=2e5+7;
typedef long long LL;
typedef double db;
using namespace std;
int n;
LL s[N],ans;
template<typename T> void read(T &x) {
char ch=getchar(); x=0; T f=1;
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') f=-1,ch=getchar();
for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
}
map<LL,LL>f;
map<LL,LL>g;
map<LL,LL>cnt;
int bo[N],p[N];
void get_prime(int n) {
For(i,2,n) {
if(!bo[i]) p[++p[0]]=i;
for(int j=1;j<=p[0]&&p[j]*i<=n;j++) {
bo[p[j]*i]=1;
if(i%p[j]==0) break;
}
}
}
void get_it(LL x) {
if(f[x]) {
LL z=f[x];
if(z==-1) ans++;
else cnt[z]++;
return;
}
LL tp=x,fx=1,gx=1;
For(i,0,325) {
if(tp%p[i]==0) {
int c=0;
while(tp%p[i]==0) {
tp/=p[i]; c++;
} c%=3;
if(c==1) fx*=p[i],gx*=(LL)p[i]*p[i];
else if(c==2) fx*=(LL)p[i]*p[i],gx*=p[i];
}
if(tp==1) break;
}
if(tp!=1) {
if(tp<=100000&&!bo[tp]) { fx*=tp; gx*=tp*tp; }
else {
LL tt=sqrt(tp);
if(tt*tt==tp) { fx*=tp; gx*=tt; }
else { fx*=tp; gx*=tp*tp; }
}
}
f[x]=fx; g[fx]=gx; cnt[fx]++;
}
#define IT map<LL,LL>::iterator
//#define DEBUG
int main() {
#ifdef DEBUG
freopen("1.in","r",stdin);
//freopen(".out","w",stdout);
#endif
read(n);
get_prime(100000);
For(i,1,n) read(s[i]);
For(i,1,n)
get_it(s[i]);
for(IT it=cnt.begin();it!=cnt.end();++it) {
LL x=it->first,y=it->second;
if(x==1&&y) ans++;
if(cnt[g[x]]<y||(cnt[g[x]]==y&&g[x]<x)) ans+=y;
}
printf("%lld\n",ans);
return 0;
}
003_e
1 //Achen
2 #include<algorithm>
3 #include<iostream>
4 #include<cstring>
5 #include<cstdlib>
6 #include<vector>
7 #include<cstdio>
8 #include<queue>
9 #include<cmath>
10 #include<set>
11 #include<map>
12 #define For(i,a,b) for(int i=(a);i<=(b);i++)
13 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
14 const int N=2e5+7;
15 typedef long long LL;
16 typedef double db;
17 using namespace std;
18 LL n,q;
19 LL a[N],cnt[N],ans[N];
20
21 template<typename T> void read(T &x) {
22 char ch=getchar(); x=0; T f=1;
23 while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
24 if(ch=='-') f=-1,ch=getchar();
25 for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
26 }
27
28 LL sg[N<<2];
29 #define lc x<<1
30 #define rc ((x<<1)|1)
31 #define mid ((l+r)>>1)
32 void build(int x,int l,int r) {
33 if(l==r) { sg[x]=a[l]; return ; }
34 build(lc,l,mid); build(rc,mid+1,r);
35 sg[x]=min(sg[lc],sg[rc]);
36 }
37
38 LL qry(int x,int l,int r,int ql,int qr,LL v) {
39 if(ql>qr) return 0;
40 if(l>=ql&&r<=qr) {
41 if(sg[x]>v) return 0;
42 if(l==r) return l;
43 if(sg[rc]<=v) return qry(rc,mid+1,r,ql,qr,v);
44 if(sg[lc]<=v) return qry(lc,l,mid,ql,qr,v);
45 }
46 if(qr<=mid) return qry(lc,l,mid,ql,qr,v);
47 LL rs=qry(rc,mid+1,r,ql,qr,v);
48 if(rs) return rs; else return qry(lc,l,mid,ql,qr,v);
49 }
50
51 LL cf[N];
52 void solve(int x,LL l,LL c) {
53 if(!x||!l) {
54 if(!x) cf[l]+=c;
55 return ;
56 }
57 int y=qry(1,1,q,1,x-1,l);
58 cnt[y]+=l/a[y]*c;
59 solve(y,l%a[y],c);
60 }
61
62 //#define DEBUG
63 int main() {
64 #ifdef DEBUG
65 freopen("1.in","r",stdin);
66 //freopen(".out","w",stdout);
67 #endif
68 read(n); read(q); a[0]=n;
69 if(q==0) {
70 For(i,1,n) puts("1");
71 return 0;
72 }
73 For(i,1,q) read(a[i]);
74 build(1,1,q); cnt[q]=1;
75 Rep(i,q,1) if(cnt[i])
76 solve(i,a[i],cnt[i]);
77 ans[n+1]=cnt[0];
78 Rep(i,n,1) ans[i]=ans[i+1]+cf[i];
79 For(i,1,n) printf("%lld\n",ans[i]);
80 return 0;
81 }
003_f
V(k-1):k-1级分形的点数,k级分形中包含2级分形的数量,ev:每个二级分形中的边数
E(k-1):k-1级分形的边数,k级分形中,多少对2级分形间有两边, ud:两个相连二级分形间的边数
//Achen
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<queue>
#include<cmath>
#include<set>
#include<map>
#define For(i,a,b) for(int i=(a);i<=(b);i++)
#define Rep(i,a,b) for(int i=(a);i>=(b);i--)
const int N=1007,mod=1e9+7;
typedef long long LL;
typedef double db;
using namespace std;
LL n,m,k,f[4]={0,0,1,0},g[4],a[N][N],b[N][N],ev,ud,lr,v;
char s[N];
template<typename T> void read(T &x) {
char ch=getchar(); x=0; T f=1;
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') f=-1,ch=getchar();
for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
}
LL ksm(LL a,LL b) {
LL rs=1,bs=a;
while(b) {
if(b&1) rs=rs*bs%mod;
bs=bs*bs%mod;
b>>=1;
}
return rs;
}
struct jz {
LL a[4][4];
friend jz operator *(const jz&A,const jz&B) {
jz rs;
For(i,0,3) For(j,0,3) {
rs.a[i][j]=0;
For(k,0,3) (rs.a[i][j]+=A.a[i][k]*B.a[k][j]%mod)%=mod;
}
return rs;
}
}bs,rs;
LL jzksm(LL b) {
while(b) {
if(b&1) rs=rs*bs;
bs=bs*bs;
b>>=1;
}
}
//#define DEBUG
int main() {
#ifdef DEBUG
freopen("1.in","r",stdin);
//freopen(".out","w",stdout);
#endif
read(n); read(m); read(k);
For(i,1,n) {
scanf("%s",s+1);
For(j,1,m) {
a[i][j]=(s[j]=='#');
v+=a[i][j];
}
}
For(i,1,n) lr+=(a[i][1]&a[i][m]);
For(i,1,m) ud+=(a[1][i]&a[n][i]);
if(lr&&ud) puts("1");
else if(!lr&&!ud) printf("%lld\n",ksm(v,k-1));
else {
if(lr) {
For(i,1,n) For(j,1,m) b[j][i]=a[i][j];
swap(n,m); swap(lr,ud);
}
else For(i,1,n) For(j,1,m) b[i][j]=a[i][j];
For(i,1,n-1) For(j,1,m) if(b[i][j]&&b[i+1][j]) ev++;
For(i,0,3) rs.a[i][i]=1;
bs.a[2][0]=1; bs.a[3][1]=1; bs.a[2][2]=v;
bs.a[2][3]=ev; bs.a[3][3]=ud;
jzksm(k-1);
For(i,0,3) For(j,0,3) (g[i]+=f[j]*rs.a[j][i]%mod)%=mod;
LL ans=(g[2]-g[3]+mod)%mod;
printf("%lld\n",ans);
}
return 0;
}
cf
round456_d
贪心,每次选被r*r的矩形包含最多的点。先把中间的点放进堆,肯定是最优的,每次选了一个点就把它周围四个点放进堆。
round456_e
把16个数分成两个集合,每个8个数,爆搜出每个集合1e18内的数的所有数,然后二分答案判断。
可持久化线段树
比遥远的国度多了个求lca。
当前根为rt,求u,v的lca,发现lca是lca(u,v),lca(u,rt),lca(v,rt)中和另两个不同的那一个。
线段树,区间gcd是x的倍数则ok,否则只能有一个数不是x的倍数,递归地找保证只有一个即可。