城乡联谊胡策会糊厕R3
因为时间关系这把没设计题面,而且居然还出了锅……T_T
信
原题是leetcode WeeklyContest52 的T1(懒得去找url了
随便搞,但是无解输-1
数字统计
原题PE603
记前n个素数组成的字符串为S
一个数字可以分成三部分,中间一段恰好为S复制某次后的结果,前面一段S的后缀,后面一段S的前缀。这3个部分分开统计。
对于每个部分,我们可以很容易写出一份暴力,然后用自然数k次前缀和的公式优化一波就可以了。
#include<ctime> #include<cassert> #include<cstdio> #include<algorithm> #define MN 2000001 #define int long long #define ju(x) assert(1||(x)>=0&&x<MOD) using namespace std; const int MOD=1e9+7; int p[MN],sum=0,num=0,K,mmh,s[MN],n,pre[MN],suf[MN]; bool bo[MN]; inline void M(int &x){while(x>=MOD)x-=MOD;while(x<0)x+=MOD;} inline int mi(long long x,long long y){ int mmh=1; while (y){ if (y&1) mmh=1LL*mmh*x%MOD; x=1LL*x*x%MOD;y>>=1; } return mmh; } signed main(){ for (int i=2;i<MN;i++){ if (!bo[i]) p[++num]=i; for (int j=1;j<=num&&i*p[j]<MN;j++) if (bo[i*p[j]]=1,i%p[j]==0) break; } num=1000000;K=1000000000000ll; //freopen("data/count1.in","r",stdin); //freopen("data/count1.out","w",stdout); //num=10000;K=1000000000000ll; //num=23;K=233; scanf("%lld%lld",&num,&K); mmh=n=0; for (int i=num;i;i--) for (int j=p[i];j;j/=10) s[n++]=j%10; for (int i=0;i<n/2;i++) swap(s[i],s[n-1-i]); for (int i=0;i<n;i++) M(pre[i]=pre[i-1]*10%MOD+s[i]); for (int i=n-1,k=1;i>=0;i--,k=1LL*k*10%MOD) M(suf[i]=1LL*s[i]%MOD*k%MOD+suf[i+1]); for (int i=0,j=0;i<n;i++) j=(1LL*j%MOD*10%MOD+1LL*s[i]%MOD*(i+1)%MOD)%MOD,M(mmh+=j); mmh=1LL*K%MOD*mmh%MOD; for (int i=0;i<n;i++) sum=(1LL*sum*10+s[i])%MOD; int MMH=1LL*K%MOD*((K-1)%MOD)%MOD*mi(2,MOD-2)%MOD*10%MOD,_MMH=0,a=mi(10,MOD-2); MMH=MOD-MMH; ju(MMH);ju(_MMH); //for (int i=0;i<K;i++) _MMH=(1LL*i%MOD*mi(a,i*n)+_MMH)%MOD; int b=mi(a,n); M(_MMH=((1LL*(K-1)%MOD*mi(b,K)+1)%MOD*mi(b-1,MOD-2)%MOD-(1LL*mi(b,K)-1)%MOD*mi(b-1,MOD-2)%MOD*mi(b-1,MOD-2)%MOD)%MOD); ju(MMH);ju(_MMH); _MMH=1LL*_MMH%MOD*mi(10,K*n-n+1)%MOD; M(mmh+=1LL*(MMH+_MMH)%MOD*n%MOD*sum%MOD*mi(9,MOD-2)%MOD); ju(MMH);ju(_MMH); for (int i=0;i<n;i++){ int MMH=1LL*(mi(10,K*n)-1)%MOD*mi(mi(10,n)-1,MOD-2)%MOD; ju(MMH); MMH=MMH*10%MOD; M(MMH-=K*10%MOD); ju(MMH); M(mmh+=suf[i]%MOD*mi(9,MOD-2)%MOD*MMH%MOD); ju(mmh); } for (int i=0;i<n;i++){ int MMH=1LL*K%MOD*((K-1)%MOD)%MOD*mi(2,MOD-2)%MOD; ju(MMH); M(mmh+=1LL*pre[i]%MOD*n%MOD*MMH%MOD); ju(mmh); } printf("%lld\n",mmh); return 0; mmh=n=0; for (int k=1;k<=K;k++) for (int i=num;i;i--) for (int j=p[i];j;j/=10) s[n++]=j%10; for (int i=0;i<n/2;i++) swap(s[i],s[n-1-i]); for (int i=0,j=0;i<n;i++) j=(1LL*j%MOD*10%MOD+1LL*s[i]%MOD*(i+1))%MOD,M(mmh+=j); printf("%lld\n",mmh); return 0; mmh=n=0; for (int k=1;k<=K;k++) for (int i=num;i;i--) for (int j=p[i];j;j/=10) s[n++]=j%10; for (int i=n-1;i>=0;i--) for (int j=i,k=0;j>=0;j--) k=(1LL*k*10+s[j])%MOD,M(mmh+=k); printf("%d\n",mmh); }
飞翔
首先把数字从大到小排个序,然后从1到n枚举以每棵树为起点的序列数,这样就每次只有一棵树从在右边的状态变成在左边的状态。
问题变成,一列格子,一些是黑色的,一些是白色的,你需要从左往右走,每次可以走到当前格子右边的任意一个点,相邻两次踩到的格子必须颜色不同。这个问题显然可以直接递推。考虑到要进行修改操作,我们可以用线段树维护矩阵乘法实现。
出题人写了3次觉得这玩意贼好写啊(不到2k的线段树
#include<cstdio> #include<algorithm> #define lp p<<1 #define rp (p<<1)|1 #define MN 400000 using namespace std; int read_p,read_ca; inline int read(){ read_p=0;read_ca=getchar(); while(read_ca<'0'||read_ca>'9') read_ca=getchar(); while(read_ca>='0'&&read_ca<='9') read_p=read_p*10+read_ca-48,read_ca=getchar(); return read_p; } int n,m,a[MN],b[MN],t[MN*4][2][2],C[2][2],Mavis[2][2],mmh=0; const int MOD=1e9+7; inline void M(int &x){while(x>=MOD)x-=MOD;while(x<0)x+=MOD;} bool cmp(int x,int y){return a[x]>a[y];} void cc(int a[2][2],int b[2][2],int c[2][2]){ int i,j,k; for (i=0;i<2;i++) for (j=0;j<2;j++) for (C[i][j]=0,k=0;k<2;k++) C[i][j]=(1LL*a[i][k]*b[k][j]+C[i][j])%MOD; for (i=0;i<2;i++) for (j=0;j<2;j++) c[i][j]=C[i][j]; } void build(int p,int l,int r){ if (l==r){ t[p][0][0]=t[p][1][1]=t[p][0][1]=1;t[p][1][0]=0; return; } int mid=l+r>>1; build(lp,l,mid);build(rp,mid+1,r); cc(t[lp],t[rp],t[p]); } void ask(int p,int l,int r,int k){ if (k<l) return; if (r<=k){ cc(Mavis,t[p],Mavis); return; } int mid=l+r>>1; ask(lp,l,mid,k);ask(rp,mid+1,r,k); } void cg(int p,int l,int r,int k){ if (l==r){ t[p][0][0]=t[p][1][1]=t[p][1][0]=1;t[p][0][1]=0; return; } int mid=l+r>>1; if (k<=mid) cg(lp,l,mid,k);else cg(rp,mid+1,r,k); cc(t[lp],t[rp],t[p]); } int main(){ n=read(); for (int i=1;i<=n;i++) a[i]=read(),b[i]=i; sort(b+1,b+1+n,cmp); for (int i=1;i<=n;i++) a[b[i]]=i; build(1,1,n); for (int i=1;i<=n;i++){ Mavis[0][0]=Mavis[0][1]=1;Mavis[1][0]=Mavis[1][1]=0; if (a[i]-1) ask(1,1,n,a[i]-1); M(mmh+=Mavis[0][0]);M(mmh+=Mavis[0][1]); cg(1,1,n,a[i]); } M(mmh-=n); printf("%d\n",mmh); }