A、签到,暴力打个表就发现规律是斐波那契数列
代码:
#include <bits/stdc++.h> #define int long long #define sc(a) scanf("%lld",&a) #define scc(a,b) scanf("%lld %lld",&a,&b) #define sccc(a,b,c) scanf("%lld %lld %lld",&a,&b,&c) #define scs(a) scanf("%s",a) #define schar(a) scanf("%c",&a) #define pr(a) printf("%lld",a) #define fo(i,a,b) for(int i=a;i<b;++i) #define re(i,a,b) for(int i=a;i<=b;++i) #define rfo(i,a,b) for(int i=a;i>b;--i) #define rre(i,a,b) for(int i=a;i>=b;--i) #define prn() printf("\n") #define prs() printf(" ") #define mkp make_pair #define pii pair<int,int> #define pub(a) push_back(a) #define pob() pop_back() #define puf(a) push_front(a) #define pof() pop_front() #define fst first #define snd second #define frt front() #define bak back() #define mem0(a) memset(a,0,sizeof(a)) #define memmx(a) memset(a,0x3f3f,sizeof(a)) #define memmn(a) memset(a,-0x3f3f,sizeof(a)) #define debug #define db double #define yyes cout<<"YES"<<endl; #define nno cout<<"NO"<<endl; #define all(i,a) for(auto i=a.begin();i!=a.end();++i) using namespace std; typedef vector<int> vei; typedef vector<pii> vep; typedef map<int,int> mpii; typedef map<char,int> mpci; typedef map<string,int> mpsi; typedef deque<int> deqi; typedef deque<char> deqc; typedef priority_queue<int> mxpq; typedef priority_queue<int,vector<int>,greater<int> > mnpq; typedef priority_queue<pii> mxpqii; typedef priority_queue<pii,vector<pii>,greater<pii> > mnpqii; const int maxn=500005; const int inf=0x3f3f3f3f3f3f3f3f; const int MOD=1e9+7; const db eps=1e-10; const db pi=3.1415926535; int qpow(int a,int b){int tmp=a%MOD,ans=1;while(b){if(b&1){ans*=tmp,ans%=MOD;}tmp*=tmp,tmp%=MOD,b>>=1;}return ans;} int lowbit(int x){return x&-x;} int max(int a,int b){return a>b?a:b;} int min(int a,int b){return a<b?a:b;} int mmax(int a,int b,int c){return max(a,max(b,c));} int mmin(int a,int b,int c){return min(a,min(b,c));} void mod(int &a){a+=MOD;a%=MOD;} bool chk(int now){} int half(int l,int r){while(l<=r){int m=(l+r)/2;if(chk(m))r=m-1;else l=m+1;}return l;} int ll(int p){return p<<1;} int rr(int p){return p<<1|1;} int mm(int l,int r){return (l+r)/2;} int lg(int x){if(x==0) return 1;return (int)log2(x)+1;} bool smleql(db a,db b){if(a<b||fabs(a-b)<=eps)return true;return false;} bool bigeql(db a,db b){if(a>b||fabs(a-b)<=eps)return true;return false;} bool eql(db a,db b){if(fabs(a-b)<eps) return 1;return 0;} db len(db a,db b,db c,db d){return sqrt((a-c)*(a-c)+(b-d)*(b-d));} bool isp(int x){if(x==1)return false;if(x==2)return true;for(int i=2;i*i<=x;++i)if(x%i==0)return false;return true;} inline int read(){ char ch=getchar();int s=0,w=1; while(ch<48||ch>57){if(ch=='-')w=-1;ch=getchar();} while(ch>=48&&ch<=57){s=(s<<1)+(s<<3)+ch-48;ch=getchar();} return s*w; } inline void write(int x){ if(x<0)putchar('-'),x=-x; if(x>9)write(x/10); putchar(x%10+48); } int gcd(int a, int b){ if(a==0) return b; if(b==0) return a; if(!(a&1)&&!(b&1)) return gcd(a>>1,b>>1)<<1; else if(!(b&1)) return gcd(a,b>>1); else if(!(a&1)) return gcd(a>>1,b); else return gcd(abs(a-b),min(a,b)); } int lcm(int x,int y){return x*y/gcd(x,y);} int f[maxn]; signed main(){ ios_base::sync_with_stdio(0); cin.tie(0),cout.tie(0); int n;cin>>n; f[1]=2,f[2]=3; re(i,3,n) f[i]=(f[i-1]+f[i-2])%MOD; cout<<f[n]; return 0; }
B、
要求下面这个怪怪公式:
\(\Sigma_{i=1}^n\Sigma_{j=1}^ii* {\lfloor \frac{i}{j} \rfloor}^j\)
范围n<=3000000,看起来似乎可以有\(O(n \sqrt{n} )\)的做法,比较直观的想法就是数论分块,枚举 \(i\) 即可
数论分块参见数论分块
但是果然T了,跑了百分之六十的数据。
现在得换种思路,枚举 \(j\) ,把 \(\frac{i}{j}\) 拿出来打表看看,会发现下面这个怪东西:
于是分成了长度为 \(j\) 的块,时间复杂度是\(O(n \ln{n} )\),调和级数确实牛批
另外还可以考虑把快速幂优化掉,每一次只维护一个数组,储存对应数字的 \(j\) 次方即可,需要的时候再让他乘以 \(j\)
代码:
#include <bits/stdc++.h> #define int long long #define sc(a) scanf("%lld",&a) #define scc(a,b) scanf("%lld %lld",&a,&b) #define sccc(a,b,c) scanf("%lld %lld %lld",&a,&b,&c) #define scs(a) scanf("%s",a) #define schar(a) scanf("%c",&a) #define pr(a) printf("%lld",a) #define fo(i,a,b) for(int i=a;i<b;++i) #define re(i,a,b) for(int i=a;i<=b;++i) #define rfo(i,a,b) for(int i=a;i>b;--i) #define rre(i,a,b) for(int i=a;i>=b;--i) #define prn() printf("\n") #define prs() printf(" ") #define mkp make_pair #define pii pair<int,int> #define pub(a) push_back(a) #define pob() pop_back() #define puf(a) push_front(a) #define pof() pop_front() #define fst first #define snd second #define frt front() #define bak back() #define mem0(a) memset(a,0,sizeof(a)) #define memmx(a) memset(a,0x3f3f,sizeof(a)) #define memmn(a) memset(a,-0x3f3f,sizeof(a)) #define debug #define db double #define yyes cout<<"YES"<<endl; #define nno cout<<"NO"<<endl; #define all(i,a) for(auto i=a.begin();i!=a.end();++i) using namespace std; typedef vector<int> vei; typedef vector<pii> vep; typedef map<int,int> mpii; typedef map<char,int> mpci; typedef map<string,int> mpsi; typedef deque<int> deqi; typedef deque<char> deqc; typedef priority_queue<int> mxpq; typedef priority_queue<int,vector<int>,greater<int> > mnpq; typedef priority_queue<pii> mxpqii; typedef priority_queue<pii,vector<pii>,greater<pii> > mnpqii; const int maxn=3000005; const int inf=0x3f3f3f3f3f3f3f3f; const int MOD=1e9+7; const db eps=1e-10; const db pi=3.1415926535; int qpow(int a,int b){int tmp=a%MOD,ans=1;while(b){if(b&1){ans*=tmp,ans%=MOD;}tmp*=tmp,tmp%=MOD,b>>=1;}return ans;} int lowbit(int x){return x&-x;} int max(int a,int b){return a>b?a:b;} int min(int a,int b){return a<b?a:b;} int mmax(int a,int b,int c){return max(a,max(b,c));} int mmin(int a,int b,int c){return min(a,min(b,c));} void mod(int &a){a+=MOD;a%=MOD;} bool chk(int now){} int half(int l,int r){while(l<=r){int m=(l+r)/2;if(chk(m))r=m-1;else l=m+1;}return l;} int ll(int p){return p<<1;} int rr(int p){return p<<1|1;} int mm(int l,int r){return (l+r)/2;} int lg(int x){if(x==0) return 1;return (int)log2(x)+1;} bool smleql(db a,db b){if(a<b||fabs(a-b)<=eps)return true;return false;} bool bigeql(db a,db b){if(a>b||fabs(a-b)<=eps)return true;return false;} bool eql(db a,db b){if(fabs(a-b)<eps) return 1;return 0;} db len(db a,db b,db c,db d){return sqrt((a-c)*(a-c)+(b-d)*(b-d));} bool isp(int x){if(x==1)return false;if(x==2)return true;for(int i=2;i*i<=x;++i)if(x%i==0)return false;return true;} inline int read(){ char ch=getchar();int s=0,w=1; while(ch<48||ch>57){if(ch=='-')w=-1;ch=getchar();} while(ch>=48&&ch<=57){s=(s<<1)+(s<<3)+ch-48;ch=getchar();} return s*w; } inline void write(int x){ if(x<0)putchar('-'),x=-x; if(x>9)write(x/10); putchar(x%10+48); } int gcd(int a, int b){ if(a==0) return b; if(b==0) return a; if(!(a&1)&&!(b&1)) return gcd(a>>1,b>>1)<<1; else if(!(b&1)) return gcd(a,b>>1); else if(!(a&1)) return gcd(a>>1,b); else return gcd(abs(a-b),min(a,b)); } int lcm(int x,int y){return x*y/gcd(x,y);} int n,inv=qpow(2,MOD-2),ans=0; int p[maxn]; int s(int l,int r){return (((r+l)*(r-l+1)%MOD)*inv)%MOD;} signed main(){ ios_base::sync_with_stdio(0); cin.tie(0),cout.tie(0); cin>>n; re(i,1,n) p[i]=i; re(j,1,n){ int flag=1; for(int i=j;i<=n;i+=j){ ans=(ans+s(i,min(i+j-1,n))*p[flag]%MOD)%MOD; p[flag]=(p[flag]*flag%MOD)%MOD; flag++; } } cout<<ans; return 0; }
C、一开始以为是什么怪怪通配符匹配,没想到是bitset大胜利
对于每个询问维护两个bitset,不妨设为A和B,如果该位是通配符,那么\(A[i]=B[i]=0\)
否则的话\(A[i]=1 B[i]=S[i]\),\(S[i]\)是读入的数组
这样有什么好处呢?我们令\(A \& bs[i]\),其中\(bs[i]\)是输入的字典,会发现通配符位置上是一定匹配的,而其他位置仍保持原状,比较一下是否相等即可
时间复杂度\(O(n^2)\)
代码:
#include <bits/stdc++.h> #define int long long #define sc(a) scanf("%lld",&a) #define scc(a,b) scanf("%lld %lld",&a,&b) #define sccc(a,b,c) scanf("%lld %lld %lld",&a,&b,&c) #define scs(a) scanf("%s",a) #define schar(a) scanf("%c",&a) #define pr(a) printf("%lld",a) #define fo(i,a,b) for(int i=a;i<b;++i) #define re(i,a,b) for(int i=a;i<=b;++i) #define rfo(i,a,b) for(int i=a;i>b;--i) #define rre(i,a,b) for(int i=a;i>=b;--i) #define prn() printf("\n") #define prs() printf(" ") #define mkp make_pair #define pii pair<int,int> #define pub(a) push_back(a) #define pob() pop_back() #define puf(a) push_front(a) #define pof() pop_front() #define fst first #define snd second #define frt front() #define bak back() #define mem0(a) memset(a,0,sizeof(a)) #define memmx(a) memset(a,0x3f3f,sizeof(a)) #define memmn(a) memset(a,-0x3f3f,sizeof(a)) #define debug #define db double #define yyes cout<<"YES"<<endl; #define nno cout<<"NO"<<endl; #define all(i,a) for(auto i=a.begin();i!=a.end();++i) using namespace std; typedef vector<int> vei; typedef vector<pii> vep; typedef map<int,int> mpii; typedef map<char,int> mpci; typedef map<string,int> mpsi; typedef deque<int> deqi; typedef deque<char> deqc; typedef priority_queue<int> mxpq; typedef priority_queue<int,vector<int>,greater<int> > mnpq; typedef priority_queue<pii> mxpqii; typedef priority_queue<pii,vector<pii>,greater<pii> > mnpqii; const int maxn=500005; const int inf=0x3f3f3f3f3f3f3f3f; const int MOD=100000007; const db eps=1e-10; const db pi=3.1415926535; int qpow(int a,int b){int tmp=a%MOD,ans=1;while(b){if(b&1){ans*=tmp,ans%=MOD;}tmp*=tmp,tmp%=MOD,b>>=1;}return ans;} int lowbit(int x){return x&-x;} int max(int a,int b){return a>b?a:b;} int min(int a,int b){return a<b?a:b;} int mmax(int a,int b,int c){return max(a,max(b,c));} int mmin(int a,int b,int c){return min(a,min(b,c));} void mod(int &a){a+=MOD;a%=MOD;} bool chk(int now){} int half(int l,int r){while(l<=r){int m=(l+r)/2;if(chk(m))r=m-1;else l=m+1;}return l;} int ll(int p){return p<<1;} int rr(int p){return p<<1|1;} int mm(int l,int r){return (l+r)/2;} int lg(int x){if(x==0) return 1;return (int)log2(x)+1;} bool smleql(db a,db b){if(a<b||fabs(a-b)<=eps)return true;return false;} bool bigeql(db a,db b){if(a>b||fabs(a-b)<=eps)return true;return false;} bool eql(db a,db b){if(fabs(a-b)<eps) return 1;return 0;} db len(db a,db b,db c,db d){return sqrt((a-c)*(a-c)+(b-d)*(b-d));} bool isp(int x){if(x==1)return false;if(x==2)return true;for(int i=2;i*i<=x;++i)if(x%i==0)return false;return true;} inline int read(){ char ch=getchar();int s=0,w=1; while(ch<48||ch>57){if(ch=='-')w=-1;ch=getchar();} while(ch>=48&&ch<=57){s=(s<<1)+(s<<3)+ch-48;ch=getchar();} return s*w; } inline void write(int x){ if(x<0)putchar('-'),x=-x; if(x>9)write(x/10); putchar(x%10+48); } int gcd(int a, int b){ if(a==0) return b; if(b==0) return a; if(!(a&1)&&!(b&1)) return gcd(a>>1,b>>1)<<1; else if(!(b&1)) return gcd(a,b>>1); else if(!(a&1)) return gcd(a>>1,b); else return gcd(abs(a-b),min(a,b)); } int lcm(int x,int y){return x*y/gcd(x,y);} int n,m,_; string s; bitset<1005> bs[1005],A,B; signed main(){ ios_base::sync_with_stdio(0); cin.tie(0),cout.tie(0); cin>>n>>m; re(i,1,n){ cin>>s; re(j,0,m-1) bs[i][j]=(s[j]=='1'); } cin>>_; while(_--){ cin>>s; re(i,0,m-1){ if(s[i]=='1') A[i]=1,B[i]=1; else if(s[i]=='0') A[i]=1,B[i]=0; else A[i]=B[i]=0; } int cnt=0; re(i,1,n){ if((A&bs[i])==B) cnt++; } cout<<cnt<<endl; } return 0; }
E、
首先把异或前缀和预处理出来,注意数组全部都得右移一位,因为要把首位的\(0\)空出来
实际上题目要维护的是某个区间内两个最近的相同数字,考虑把询问按照右端点排序
由于值域较小,我们保存每个数字上一次出现的位置,并且单点更新那一点的最小值
最后区间询问最小值即可
注意\(0\)很特别,它第一次的出现位置应该在\(1\),所以在上面才把数组右移一位
代码:
#include <bits/stdc++.h> using namespace std; const int maxn=500005; int n,Q; struct node{ int l,r,id; }q[maxn]; int a[maxn],last[maxn*4],mn[maxn*4],ans[maxn]; bool cmp(node a,node b){ if(a.r!=b.r) return a.r<b.r; else return a.l<b.l; } int ask(int L,int R,int p=1,int l=1,int r=n){ if(L<=l&&r<=R){ return mn[p]; } int m=(l+r)/2; int ret=0x3f3f3f3f; if(L<=m) ret=min(ret,ask(L,R,p*2,l,m)); if(R>m) ret=min(ret,ask(L,R,p*2+1,m+1,r)); return ret; } void modi(int pos,int val,int p=1,int l=1,int r=n){ // cout<<"NMSL"<<endl; if(l==r&&l==pos){ mn[p]=val; // cout<<"??? "<<l<<' '<<val<<endl; return; } int m=(l+r)/2; if(pos<=m) modi(pos,val,p*2,l,m); else modi(pos,val,p*2+1,m+1,r); mn[p]=min(mn[p*2],mn[p*2+1]); } int main(){ scanf("%d%d",&n,&Q); n++; for(int i=2;i<=n;++i) scanf("%d",&a[i]); a[1]=0; for(int i=2;i<=n;++i) a[i]^=a[i-1]; for(int i=1;i<=Q;++i) scanf("%d%d",&q[i].l,&q[i].r),q[i].id=i; sort(q+1,q+1+Q,cmp); memset(mn,0x3f,sizeof(mn)); last[0]=1; int flag=2; for(int i=1;i<=Q;++i){ while(flag<=q[i].r+1){ int v=flag-last[a[flag]]; // printf("QAQ %d %d %d\n",flag,a[flag],last[a[flag]]); if(last[a[flag]]!=0) modi(last[a[flag]],v); last[a[flag]]=flag; flag++; } // printf("! %d %d\n",q[i].l,q[i].r+1); ans[q[i].id]=ask(q[i].l,q[i].r+1); } for(int i=1;i<=Q;++i) printf("%d\n",(ans[i]==0x3f3f3f3f)?-1:ans[i]); return 0; } /* 5 3 1 2 3 4 5 1 5 1 1 1 3 */