闷声发大财
A
O(nmk)dp即可,因为带了1/2的常数+2s所以很稳
#include <algorithm> #include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #define fo(a,b,c) for (a=b; a<=c; a++) #define fd(a,b,c) for (a=b; a>=c; a--) #define min(a,b) (a<b?a:b) using namespace std; int a[801]; int p[801][801]; long long f[801][801]; int n,m,i,j,k,l,K,Y; int main() { // freopen("a.in","r",stdin); scanf("%d%d%d%d",&n,&m,&K,&Y); fo(i,1,n) scanf("%d",&a[i]); fo(i,1,n) { fo(j,1,m) { scanf("%d",&p[i][j]); if (j<Y) p[i][j]+=a[i]*j; } } memset(f,127,sizeof(f)); f[0][0]=0; fo(i,0,n-1) { fo(j,0,K) if (f[i][j]<800000000000ll) { fd(k,min(K-j,m),0) f[i+1][j+k]=min(f[i+1][j+k],f[i][j]+p[i+1][k]); } } printf("%lld\n",f[n][K]); }
B
m=2的约瑟夫问题,给出一个人求n=1~n时剩下这个人的方案&最大的n
约瑟夫的O(n)递推显然过不了,但是随便打表可以发现答案长这样:
1 1 3 1 3 5 7 1 3 5 7 9 11 13 15 1...
随便算
#include <algorithm> #include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #define fo(a,b,c) for (a=b; a<=c; a++) #define fd(a,b,c) for (a=b; a>=c; a--) using namespace std; //int f[233]; long long n,m,s,S,ans1,ans2; int main() { // freopen("b.in","r",stdin); scanf("%lld%lld",&n,&m); if (!(m&1)) { printf("0 0\n"); return 0; } S=0;s=1; while (n) { if (n>=s) { n-=s; if (m<=s*2-1) ++ans1,ans2=S+(m+1)/2; } else { if (m<=n*2-1) ++ans1,ans2=S+(m+1)/2; n=0; } S+=s; s=s*2; } printf("%lld %lld\n",ans1,ans2); return 0; // f[1]=0; // fo(i,2,100) // f[i]=(f[i-1]+2)%i; // // fo(i,1,100) // cout<<f[i]+1<<" "; // if (!f[i]) // cout<<f[i-1]+1<<" "; }
C
在普通循环同构的基础上加上了对角互换
懒得画
假设有一条直线穿过圆,并且保证直线上方的数<=对应的直线下方的数
这样解决了对角互换的条件
然后将圆旋转,可以发现上下两部分同时旋转了
于是可以把一对对应点看成一个元素,那么变成元素种数为m(m+1)/2,环的大小为n的普通轮换问题
直接O(n)枚举会挂,所以枚举gcd,再乘上phi(n/gcd)即可
#include <algorithm> #include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #include <cmath> #define fo(a,b,c) for (a=b; a<=c; a++) #define fd(a,b,c) for (a=b; a>=c; a--) #define mod 19260817 #define Mod 19260815 using namespace std; int f[mod+1]; int p[1226565]; int T,i,j,k,l,len,s; long long n,m,ans; void init() { int i,j; fo(i,1,mod) f[i]=i; fo(i,2,mod) { if (f[i]==i) { --f[i]; p[++len]=i; } fo(j,1,len) if ((long long)i*p[j]<=mod) { if (!(i%p[j])) { f[i*p[j]]=f[i]*p[j]; break; } else f[i*p[j]]=f[i]*(p[j]-1); } else break; } } long long qpower(long long a,int b) { long long ans=1; while (b) { if (b&1) ans=ans*a%mod; a=a*a%mod; b>>=1; } return ans; } int gcd(int n,int m) { int r=n%m; while (r) { n=m; m=r; r=n%m; } return m; } int main() { // freopen("c.in","r",stdin); init(); scanf("%d",&T); for (;T;--T) { scanf("%lld%lld",&n,&m); m=m*(m+1)/2%mod; s=floor(sqrt(n)); ans=0; fo(i,1,s) if (!(n%i)) { ans=(ans+qpower(m,i)*f[n/i]%mod)%mod; if (i*i!=n) ans=(ans+qpower(m,n/i)*f[i]%mod)%mod; } // ans=(ans+qpower(m,gcd(n,i)))%mod; ans=ans*qpower(n,Mod)%mod; printf("%lld\n",ans); } }
D
sb题
把平面旋转45°再扩大\(\sqrt{2}\)倍(即(x,y)-->(x+y,y-x)),变成D*D的矩形操作
排序+扫描线
注意边界不能减
#include <algorithm> #include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #define fo(a,b,c) for (a=b; a<=c; a++) #define fd(a,b,c) for (a=b; a>=c; a--) #define max(a,b) (a>b?a:b) #define min(a,b) (a<b?a:b) #define low(x) (x&-(x)) #define N 200001 using namespace std; struct type{ int x,y,s; } a[200001]; int tr[4*N+1]; int tot,n,D,L,i,j,k,l,x,y,sum; long long ans; bool cmp(type a,type b) { return a.x<b.x || a.x==b.x && a.s<b.s; } void change(int t,int l,int r,int x,int s) { int mid=(l+r)/2; tr[t]+=s; if (l==r) return; if (x<=mid) change(t*2,l,mid,x,s); else change(t*2+1,mid+1,r,x,s); } int find(int t,int l,int r,int x,int y) { int mid=(l+r)/2,ans=0; if (x<=l && r<=y) return tr[t]; if (x<=mid) ans+=find(t*2,l,mid,x,y); if (mid<y) ans+=find(t*2+1,mid+1,r,x,y); return ans; } int main() { // freopen("d.in","r",stdin); scanf("%d%d%d",&n,&D,&L); fo(i,1,n) { scanf("%d%d",&x,&y); j=x;k=y; x=j+k; y=k-j; a[++tot]={x,y,1}; a[++tot]={x+D,y,-1}; } sort(a+1,a+tot+1,cmp); fo(i,1,tot) { if (a[i].s==1) { ans+=sum-find(1,1,N,max(a[i].y+100001-D+1,1),min(a[i].y+100001+D-1,N)); ++sum; } change(1,1,N,a[i].y+100001,a[i].s); } printf("%lld\n",ans); }
E
用总数-没有交点的即可,删除可以看成加了一个-1的矩形
求出每个询问上下左右的矩形个数,再减去四个角上的
注意时间也算一维(不用排序),所以需要cdq
#include <algorithm> #include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #define fo(a,b,c) for (a=b; a<=c; a++) #define fd(a,b,c) for (a=b; a>=c; a--) #define low(x) (x&-(x)) using namespace std; struct type{ int x1,y1,x2,y2,s,id; } a[100001],b[100001]; struct Type{ int s,id; } c[200001]; struct type1{ int x,s,id; } d[100001]; struct type2{ int x,y,s,id,Id; } D[100001]; int tr[200001]; int ans[200001]; int n,i,j,k,l,tp,tot,Tot,sum,len; bool Cmp(Type a,Type b) {return a.s<b.s;} bool cmp(type2 a,type2 b) {return a.x<b.x || a.x==b.x && a.id>b.id;} void change(int t,int s) { while (t<=200000) { tr[t]+=s; t+=low(t); } } void clear(int t) { while (t<=200000) { tr[t]=0; t+=low(t); } } int find(int t) { int ans=0; while (t) { ans+=tr[t]; t-=low(t); } return ans; } void work1() { int i; fo(i,1,n) if (d[i].s) change(d[i].x,d[i].s); else ans[d[i].id]-=find(d[i].x-1); memset(tr,0,sizeof(tr)); } void work2(int l,int r) { int i,mid=(l+r)/2; if (l==r) return; work2(l,mid); work2(mid+1,r); sort(D+l,D+r+1,cmp); fo(i,l,r) if (D[i].Id<=mid && D[i].s) change(D[i].y,D[i].s); else if (D[i].Id>mid && !D[i].s) ans[D[i].id]+=find(D[i].y-1); fo(i,l,r) if (D[i].Id<=mid && D[i].s) clear(D[i].y); } int main() { // freopen("e.in","r",stdin); scanf("%d",&n); fo(i,1,n) { scanf("%d",&tp); switch (tp) { case 1:{ scanf("%d%d%d%d",&a[i].x1,&a[i].y1,&a[i].x2,&a[i].y2); ++sum; a[i].s=1; b[++tot]=a[i]; break; } case 2:{ scanf("%d",&j); --sum; a[i]=b[j]; a[i].s=-1; break; } case 3:{ scanf("%d%d%d%d",&a[i].x1,&a[i].y1,&a[i].x2,&a[i].y2); a[i].id=++Tot; ans[Tot]=sum; break; } } } // --- len=0; fo(i,1,n) { c[++len]={a[i].x1,i}; c[++len]={a[i].x2,-i}; } sort(c+1,c+len+1,Cmp); j=0; fo(i,1,len) { j+=i==1 || c[i].s!=c[i-1].s; if (c[i].id>0) a[c[i].id].x1=j; else a[-c[i].id].x2=j; } len=0; fo(i,1,n) { c[++len]={a[i].y1,i}; c[++len]={a[i].y2,-i}; } sort(c+1,c+len+1,Cmp); j=0; fo(i,1,len) { j+=i==1 || c[i].s!=c[i-1].s; if (c[i].id>0) a[c[i].id].y1=j; else a[-c[i].id].y2=j; } // --- fo(i,1,n) if (a[i].s) d[i]={a[i].x2,a[i].s,0}; else d[i]={a[i].x1,0,a[i].id}; work1(); fo(i,1,n) if (a[i].s) d[i]={200001-a[i].x1,a[i].s,0}; else d[i]={200001-a[i].x2,0,a[i].id}; work1(); fo(i,1,n) if (a[i].s) d[i]={a[i].y2,a[i].s,0}; else d[i]={a[i].y1,0,a[i].id}; work1(); fo(i,1,n) if (a[i].s) d[i]={200001-a[i].y1,a[i].s,0}; else d[i]={200001-a[i].y2,0,a[i].id}; work1(); // --- fo(i,1,n) if (a[i].s) D[i]={a[i].x2,a[i].y2,a[i].s,0}; else D[i]={a[i].x1,a[i].y1,0,a[i].id}; fo(i,1,n) D[i].Id=i; work2(1,n); fo(i,1,n) if (a[i].s) D[i]={200001-a[i].x1,200001-a[i].y1,a[i].s,0}; else D[i]={200001-a[i].x2,200001-a[i].y2,0,a[i].id}; fo(i,1,n) D[i].Id=i; work2(1,n); fo(i,1,n) if (a[i].s) D[i]={a[i].x2,200001-a[i].y1,a[i].s,0}; else D[i]={a[i].x1,200001-a[i].y2,0,a[i].id}; fo(i,1,n) D[i].Id=i; work2(1,n); fo(i,1,n) if (a[i].s) D[i]={200001-a[i].x1,a[i].y2,a[i].s,0}; else D[i]={200001-a[i].x2,a[i].y1,0,a[i].id}; fo(i,1,n) D[i].Id=i; work2(1,n); // --- fo(i,1,Tot) printf("%d\n",ans[i]); }