cqoi2018
題解:
很多模板題
第一次寫莫隊還比較順利
除了把排序的cmp寫錯。。(還第一次遇到)
這題分塊也可以
先預處理出g[i][j]代表前i個塊,顏色為j的有多少種
f[i][j]表示i-j的塊能構成多少對
處理的方法就是f[i][j-1]+j塊內和j與j之前
算答案的時候即整塊+兩個單獨塊內部和兩個單獨塊與整塊之間
因為分塊有幾個地方都是$n\sqrt{n}$的 所以分塊的常數比莫隊要來的大
#include <bits/stdc++.h>using namespace std;#define rint register int#define IL inline#define rep(i,h,t) for (int i=h;i<=t;i++)#define dep(i,t,h) for (int i=t;i>=h;i--)#define ll long long #define me(x) memset(x,0,sizeof(x))namespace IO{char ss[1<<24],*A=ss,*B=ss;IL char gc(){return A==B&&(B=(A=ss)+fread(ss,1,1<<24,stdin),A==B)?EOF:*A++;}template<class T>void read(T &x){rint f=1,c; while (c=gc(),c<48||c>57) if (c=='-') f=-1; x=(c^48);while (c=gc(),c>47&&c<58) x=(x<<3)+(x<<1)+(c^48); x*=f;}char sr[1<<24],z[20]; int Z,C=-1;template<class T>void wer(T x){if (x<0) sr[++C]='-',x=-x;while (z[++Z]=x%10+48,x/=10);while (sr[++C]=z[Z],--Z);}IL void wer1(){sr[++C]=' ';}IL void wer2(){sr[++C]='\n';}template<class T>IL void maxa(T &x,T y) {if (x<y) x=y;}template<class T>IL void mina(T &x,T y) {if (x>y) x=y;}template<class T>IL T MAX(T x,T y){return x>y?x:y;}template<class T>IL T MIN(T x,T y){return x<y?x:y;}};using namespace IO;const int N=1e5+10;const int M=350;int n,m,k,block,q;int a[N],pos[N],b[N],now1[N],now2[N];ll ans2[N];struct re{int a,b,c;}p[N];ll ans=0;bool cmp(re x,re y){return pos[x.a]<pos[y.a]||(pos[x.a]==pos[y.a]&&x.b<y.b);}IL void insert1(int x,int y){if (y==1){now2[b[x]]+=y;now1[b[x-1]]+=y;}ans+=now2[b[x-1]^k]*y;if (y==-1){now2[b[x]]+=y;now1[b[x-1]]+=y;}}IL void insert2(int x,int y){if (y==1){now2[b[x]]+=y;now1[b[x-1]]+=y;}ans+=now1[b[x]^k]*y;if (y==-1){now2[b[x]]+=y;now1[b[x-1]]+=y;}}int main(){freopen("1.in","r",stdin);freopen("1.out","w",stdout);read(n); read(q); read(k);rep(i,1,n) read(a[i]);block=sqrt(n);m=(n-1)/block+1;rep(i,1,n) pos[i]=(i-1)/block+1;rep(i,1,q)read(p[i].a),read(p[i].b),p[i].c=i;sort(p+1,p+q+1,cmp);rep(i,1,n) b[i]=b[i-1]^a[i];rep(i,p[1].a,p[1].b){now1[b[i-1]]++;ans+=now1[b[i]^k];now2[b[i]]++;}ans2[p[1].c]=ans;rep(i,2,q){if (p[i].a>p[i-1].a)rep(j,p[i-1].a,p[i].a-1)insert1(j,-1);else dep(j,p[i-1].a-1,p[i].a) insert1(j,1);if (p[i].b>p[i-1].b)rep(j,p[i-1].b+1,p[i].b) insert2(j,1);else dep(j,p[i-1].b,p[i].b+1) insert2(j,-1);ans2[p[i].c]=ans;}rep(i,1,q) wer(ans2[i]),wer2();fwrite(sr,1,C+1,stdout);return 0;}?
題目上面畫個矩形下面用點真的是傻逼
要是是矩形的畫就比較麻煩 要判斷4條邊是否與那個線相交
可以寫特殊處理 當然也可以直接用計算幾何里的線段與線段相交判定了
要是直線的畫直接叉積就可以了
預處理一下再狀壓dp
不太卡常
#include <bits/stdc++.h> using namespace std; #define rint register int #define IL inline #define rep(i,h,t) for (int i=h;i<=t;i++) #define dep(i,t,h) for (int i=t;i>=h;i--) #define ll long long #define me(x) memset(x,0,sizeof(x)) namespace IO {char ss[1<<24],*A=ss,*B=ss;IL char gc(){return A==B&&(B=(A=ss)+fread(ss,1,1<<24,stdin),A==B)?EOF:*A++;}template<class T>void read(T &x){rint f=1,c; while (c=gc(),c<48||c>57) if (c=='-') f=-1; x=(c^48);while (c=gc(),c>47&&c<58) x=(x<<3)+(x<<1)+(c^48); x*=f;}char sr[1<<24],z[20]; int Z,C=-1;template<class T>void wer(T x){if (x<0) sr[++C]='-',x=-x;while (z[++Z]=x%10+48,x/=10);while (sr[++C]=z[Z],--Z);}IL void wer1(){sr[++C]=' ';}IL void wer2(){sr[++C]='\n';}template<class T>IL void maxa(T &x,T y) {if (x<y) x=y;}template<class T>IL void mina(T &x,T y) {if (x>y) x=y;}template<class T>IL T MAX(T x,T y){return x>y?x:y;}template<class T>IL T MIN(T x,T y){return x<y?x:y;} }; using namespace IO; double ee=1.0000000000000000; const double eps=1e-9; const int N=(1<<20)+1000; const int mo=100000007; int n; int f[21][N]; int p[40][40]; struct re{int x,y; }a[40]; IL void js(register int &x,register int y) {x=(x+y>mo)?x+y-mo:x+y; } int main() {freopen("1.in","r",stdin);freopen("1.out","w",stdout);read(n);rep(i,1,n){read(a[i].x); read(a[i].y);}rep(i,1,n)rep(j,1,n)if (i!=j)rep(k,1,n)if (k!=i&&k!=j){/*if (a[i].x==a[j].x){if (a[k].x==a[i].x&&a[k].y>=MIN(a[i].y,a[j].y)&&a[k].y<=MAX(a[i].y,a[j].y))p[i][j]|=(1<<(k-1));}else{double now=ee*(a[j].y-a[i].y)/(a[j].x-a[i].x)*(a[k].x-a[i].x)+a[i].y;if (a[k].x<=MAX(a[i].x,a[j].x)&&a[k].x>=MIN(a[i].x,a[j].x)&&now+eps>a[k].y&&now<a[k].y+1) p[i][j]|=(1<<(k-1));}*/if (a[k].x<=MAX(a[i].x,a[j].x)&&a[k].x>=MIN(a[i].x,a[j].x)&&a[k].y<=MAX(a[i].y,a[j].y)&&a[k].y>=MIN(a[i].y,a[j].y)&&(a[k].x-a[i].x)*(a[j].y-a[k].y)-(a[j].x-a[k].x)*(a[k].y-a[i].y)==0)p[i][j]|=1<<(k-1);}rep(i,1,n) f[i][1<<(i-1)]=1;int l=(1<<n)-1;int ans=0;rep(i,1,l)rep(j,1,n)if (f[j][i]){rep(k,1,n)if (((i>>(k-1))&1)==0&&(p[j][k]&(~i))==0) js(f[k][i|(1<<(k-1))],f[j][i]);if (__builtin_popcount(i)>=4) js(ans,f[j][i]);}wer(ans);fwrite(sr,1,C+1,stdout);return 0; }?
[CQOI2018]交錯序列
這可能是六題里唯一一題不是模板的題
首先最暴力的做法
就是$f[i][j][0/1]$表示前i個數有j個1且當前是0/1的方案數
復雜度$O(n^2)$
發現這個dp方程比較簡單,考慮直接用數學方法求解
先放1,然后再插空 答案就是$C(n-k+1,k)*k^a*(n-k)^b$
這個東西$nlogn$ 因為模數比較小 所以組合數需要用lucas定理計算
據游記所說這種做法好像并不能卡過?
晚上寫
然后注意到這題a,b比較小
考慮去展開$k^a*(n-k)^b$
會發現我們只需要維護$k^{1~(a+b)}$就可以了
然后$(k+1)^x$這個東西又可以用關于k的次方遞推
于是就可以上矩陣快速冪了
時間復雜度$(a+b)^3*logn$
轉載于:https://www.cnblogs.com/yinwuxiao/p/10018490.html
總結
- 上一篇: 第七周学习笔记
- 下一篇: java概述、安装、配置环境、运行