T1:Makik 学数学
Problem:
Solution:
一个非常非常非常非常显然的数位 DP
[L,R] = [1,R] - [1,L-1]
所以是分别求两次小于等于某个数字的方案数
f[i,j,k) 表示从低位数起的第 i 位,按照规则计算后答案为 j (j=0,1)
k 表示只考虑后面结尾和 lmt 后面几位 的大小关系 (k=0,1)
考虑第 i+1 位,算一下新构成的数字并判断下大小就可以了
注意到 L,R 数据范围特别大,需要用高精度,最后结果要以二进制输出,所以可以对高精度压位
Code:
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=202; 4 const int B=7; 5 const int P=(1<<30)-1; 6 char s[maxn]; 7 int T,n,y,i,j,k,t,a[maxn]; 8 struct Num{ 9 int x[B]; 10 Num(){ 11 for(int i=0;i<B;i++) x[i]=0; 12 } 13 Num operator+(Num b){ 14 Num c; 15 for(int i=0;i<B;i++) c.x[i]=x[i]+b.x[i]; 16 for(int i=0;i<B-1;i++){ 17 if(c.x[i]>P){ 18 c.x[i+1]++; 19 c.x[i]&=P; 20 } 21 } 22 return c; 23 } 24 Num operator-(Num b){ 25 Num c; 26 for(int i=0;i<B;i++) c.x[i]=x[i]-b.x[i]; 27 for(int i=0;i<B-1;i++){ 28 if(c.x[i]<0){ 29 c.x[i+1]--; 30 c.x[i]+=P+1; 31 } 32 } 33 return c; 34 } 35 void operator+=(Num b){*this=*this+b;} 36 void operator-=(Num b){*this=*this-b;} 37 void write(){ 38 int i; 39 for(i=maxn-1;~i;i--) if(x[i/30]&(1<<i%30)) break; 40 if(i<0) putchar('0'); 41 for(;~i;i--) putchar(x[i/30]&(1<<i%30)?'1':'0'); 42 } 43 }f[maxn][2][2],tmp,ans,one; 44 Num cal(){ 45 scanf("%s",s+1); 46 for(i=1;i<=n;i++){ 47 a[n-i+1]=s[i]-'0'; 48 f[i][0][0]=f[i][0][1]=f[i][1][0]=f[i][1][1]=Num(); 49 } 50 for(t=0;t<=1;t++) f[1][t][t<a[1]]+=one; 51 for(i=1;i<n;i++){ 52 for(j=0;j<=1;j++){ 53 for(k=0;k<=1;k++){ 54 for(t=0;t<=1;t++){ 55 f[i+1][!j&&!t][t==a[i+1]?k:t<a[i+1]]+=f[i][j][k]; 56 } 57 } 58 } 59 } 60 return f[n][y][1]; 61 } 62 int main(){ 63 one.x[0]=1; 64 scanf("%d",&T); 65 while(T--){ 66 scanf("%d%d",&n,&y); 67 tmp=cal(); 68 ans=cal(); 69 for(k=a[1],i=2;i<=n;i++) k=!k&&!a[i]; 70 if(k==y) ans+=one; 71 ans-=tmp; 72 ans.write(); 73 puts(""); 74 } 75 return 0; 76 }
T2:Makik 的机器
Problem:
Solution:
模拟
Code:
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int inf=1e9; 4 int T,n; 5 signed main(){ 6 scanf("%d",&T); 7 while(T--){ 8 scanf("%d",&n); 9 bool b=1,s=0; 10 int mnw=inf,mnl=inf; 11 int mxw=0,mxl=0; 12 for(int i=1;i<=n;i++){ 13 int w1,w2,l1,l2; 14 scanf("%d%d%d%d",&w1,&w2,&l1,&l2); 15 if(w1<mnw) mnw=w1,b=0; 16 if(w2>mxw) mxw=w2,b=0; 17 if(l1<mnl) mnl=l1,b=0; 18 if(l2>mxl) mxl=l2,b=0; 19 if(b==0) s=0; 20 if(w1<=mnw&&w2>=mxw&&l1<=mnl&&l2>=mxl) s=1; 21 b=1; 22 } 23 if(s==1) cout<<"TAK"<<endl; 24 else cout<<"NIE"<<endl; 25 } 26 return 0; 27 }
T3:数学家 Makik
Problem:
Solution:
这是个莫比乌斯反演题
出题人相出个数论和数据结构的综合题,但是找不到NOIP级别的,没办法只能忍痛割爱出个莫比乌斯,话说回来,莫比乌斯要是会了,其他的应该也就会了……(吧
看这个操作 1 n d kv
相当于 a[x] += v[gcd(x,n) = d]
v[gcd(x,n) = d] = v[gcd(x/d,n/d) = 1] = v Σ(k|gcd(x/d,n/d)) μ(k) = v Σ(k|(x/d),k|(n/d)) μ(k) = Σ(k|(n/d),k*d|x) v*μ(k)
如果按照操作来说我们现在其实就是枚举了所有的 n/d 的约数 k , 然后枚举所有 kd 的倍数,对应位置加上 vμ(k)就行了。 查询 O(1)查询
但是这样修改的复杂度太大,查询的复杂度太低,不妨让修改的时候枚举约数,查询的时候也枚举约数。也即我们修改的时候,新开一个数组 f,枚举约数之后只让 kd 加上 vμ(k) 查询的时候查询 Σ(i=1~n) Σ(d|i) f(d) = Σ(d=1~n) f(d) (n/d)
后面的东西跟根号分块就行了,前面的东西始终是个区间和,单点修改区间求和,使用树状数组就可以了
时间复杂度O(q√l log l + l log l)。
Code:
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 const int maxn=200001; 5 const int maxm=2480000; 6 int T,n,m,i,j,x,y,z,p[maxn],tot,g[maxn]; 7 int nxt[maxm],v[maxm],ed,op,mu[maxn]; 8 ll b[maxn],t; 9 bool vis[maxn]; 10 inline void addedge(int x,int y){ 11 v[++ed]=y; 12 nxt[ed]=g[x]; 13 g[x]=ed; 14 } 15 inline void add(int x,int y){ 16 for(;x<=n;x+=x&-x) b[x]+=y; 17 } 18 inline ll sum(int x){ 19 ll t=0; 20 for(;x;x-=x&-x) t+=b[x]; 21 return t; 22 } 23 int main(){ 24 for(mu[1]=1,i=2;i<maxn;i++){ 25 if(!vis[i]){ 26 p[++tot]=i; 27 mu[i]=-1; 28 } 29 for(j=1;j<=tot;j++){ 30 if(i*p[j]>=maxn) break; 31 vis[i*p[j]]=1; 32 if(i%p[j]) mu[i*p[j]]=-mu[i]; 33 else{ 34 mu[i*p[j]]=0; 35 break; 36 }; 37 } 38 } 39 for(i=1;i<maxn;i++){ 40 for(j=i;j<maxn;j+=i) addedge(j,i); 41 } 42 while(1){ 43 scanf("%d%d",&n,&m); 44 if(!n) return 0; 45 for(i=1;i<=n;i++) b[i]=0; 46 printf("Case #%d:\n",++T); 47 while(m--){ 48 scanf("%d%d",&op,&x); 49 if(op==1){ 50 scanf("%d%d",&y,&z); 51 if(x%y==0){ 52 for(i=g[x/y];i;i=nxt[i]){ 53 add(v[i]*y,z*mu[v[i]]); 54 } 55 } 56 } 57 else{ 58 for(t=0,i=1;i<=x;i=j+1){ 59 j=x/(x/i); 60 t+=(sum(j)-sum(i-1))*(x/i); 61 } 62 printf("%lld\n",t); 63 } 64 } 65 } 66 }