第一题太亏了、、
TMD p竟然是定值、那还输入NM啊、、、
样例p=4还是错的、、、
实际上看到这个题就已经有了30分做法,也有了一点正解的思路
但是、、、tmd p是定值、、、
感人的爆0了
30分做法:
30分代码:
#include<iostream>
#include<cstdio>
using namespace std;
#define ll int
ll x,y,n,i,p;
long long ans;
ll tong[300001];
int ni[300001];
ll jilu;
ll lin;
long long quai(long long a,long long b)
{
long long daan=1;
while(b!=0)
{
if(b%2==1)daan=daan*a%p;
b/=2;
a=(a*a)%p;
}
return daan;
}
int main()
{
freopen("tyrrell.in","r",stdin);
freopen("tyrrell.out","w",stdout);
cin>>n>>p;
ans=1;
tong[1]++;
for(i=1;i<p;i++)ni[i]=quai(i,p-2);
for(i=1;i<=n;i++)
{
// if(i==n/2)cout<<"pp";
lin=n-i+1;
if(!(lin%p))
{
lin=lin/p%p;
jilu++;
}
ans=1ll*ans*lin%p;
if(!(i%p))
{
ans=1ll*ans*ni[i/p%p]%p;
jilu--;
}else ans=1ll*ans*(ni[i%p])%p;
if(jilu>0){tong[0]++;}else {tong[ans]++;}
}
for(i=0;i<p;i++)
{
tong[i]%=29;
if(tong[i]>=10)
{
printf("%c",tong[i]-10+'A');
}else printf("%d",tong[i]);
}
}
更高分做法:NNT+数位dp:
没学、
此题有线段树做法,即
会了吧?一个简单的前缀和+两颗线段树、
但很慢且不好打而且不会维护(至少对于我)
然后上巨难理解的代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define rep(i, b) for(int i=0,nn=int(b); i<nn;++i)
#define REP(i,a,b) for(int i=int(a),nn=int(b);i<=nn;++i)
#define VEP(i,a,b) for(int i=int(a),nn=int(b);i>=nn;--i)
typedef long long ll;
using namespace std;
const int N = 100010;
struct qury {
int tp, l, r, d, tm;
qury(int tp=0,int l=0,int r=0,int d=0,int tm=0)
:tp(tp), l(l), r(r), d(d), tm(tm){}
} qy[N];
int xbt[N], ybt[N], abt[N], lod[N], rod[N], px[N], py[N];
int _x, _y, __x, __y, n, m, as1[N], as2[N];
inline void in(int &x) {
char ch=getchar(); int f=1;
for (;ch<'0'||ch>'9';ch=getchar()) if (ch=='-') f=-1;
for (x=0; ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-48;
x *= f;
}
inline bool lcmp(int a, int b) { return qy[a].l < qy[b].l; }
inline bool rcmp(int a, int b) { return qy[a].r < qy[b].r; }
inline void xbt_ad(int x,int v) {for(;x<=m;x+=x&(-x))xbt[x]+=v;}
inline void ybt_ad(int x,int v) {for(;x<=m;x+=x&(-x))ybt[x]+=v;}
inline void abt_ad(int x,int v) {for(;x<=m;x+=x&(-x))abt[x]+=v;}
inline int xbt_qy(int x,int sm=0) {for(;x;x-=x&(-x))sm+=xbt[x];return sm;}
inline int ybt_qy(int x,int sm=0) {for(;x;x-=x&(-x))sm+=ybt[x];return sm;}
inline int abt_qy(int x,int sm=0) {for(;x;x-=x&(-x))sm+=abt[x];return sm;}
inline void come(qury ths) {
int tp=ths.tp, d=ths.d, tm=ths.tm;
if (tp==1) xbt_ad(tm, d);
if (tp==2) ybt_ad(tm, d);
if (tp==3) as1[tm] = abt_qy(tm);
}
inline void leave(qury ths) {
int tp=ths.tp, d=ths.d, tm=ths.tm;
if (tp==1) xbt_ad(tm, -d);
if (tp==2) ybt_ad(tm, -d);
if (tp==3) as2[tm] = abt_qy(tm);
}
inline void contribute(int x, int y) {
int xl, xr, yl, yr, l, r, mid, tl, tr;
l = 0, r = m, xl = m+1;
while (l <= r) { mid = (l+r)>>1;
if (x + xbt_qy(mid)>=_x) xl=mid, r=mid-1;
else l = mid+1;
}
l = 0, r = m, xr = -1;
while (l <= r) { mid = (l+r)>>1;
if (x + xbt_qy(mid)<=__x) xr=mid, l=mid+1;
else r = mid-1;
}
l = 0, r = m, yl = m+1;
while (l <= r) { mid = (l+r)>>1;
if (y + ybt_qy(mid)>=_y) yl=mid, r=mid-1;
else l = mid+1;
}
l = 0, r = m, yr = -1;
while (l <= r) { mid = (l+r)>>1;
if (y + ybt_qy(mid)<=__y) yr=mid, l=mid+1;
else r = mid-1;
}
tl = max(xl, yl), tr = min(xr, yr);
if (tl < 1) tl=1; if (tr > m) tr = m;
if (tl > tr) return;
abt_ad(tl, 1) , abt_ad(tr+1, -1);
}
int main() {
freopen("particle.in", "r", stdin);
freopen("particle.out", "w", stdout);
in(n), in(_x), in(_y), in(__x), in(__y);//读入
REP(i, 1, n) in(px[i]), in(py[i]);
in(m); REP(i, 1, m) {
in(qy[i].tp), in(qy[i].l), in(qy[i].r);
if (qy[i].tp != 3) in(qy[i].d);
qy[i].tm = i, lod[i]=i, rod[i]=i;
}
sort(lod+1, lod+1+m, lcmp);
sort(rod+1, rod+1+m, rcmp);
int x, y, li=0, ri=0;
REP(i, 1, n) { x=px[i], y=py[i];
while (li < m && qy[lod[li+1]].l<=i) come(qy[lod[++li]]);
contribute(x, y);
while (ri < m && qy[rod[ri+1]].r<=i) leave(qy[rod[++ri]]);
}
REP(i, 1, m) if (qy[i].tp==3) printf("%d\n", as2[i]-as1[i]);
return 0;
}
扫描线+树状数组*3+差分**3+二分+双排序离散+3重判定
这个码理解了,思维层次就会上升很大的一个高度、
理解难度直逼TA 的 running
模拟推了好几遍(ps:模拟代码真的不是理解代码的一个好方法)
读着都快哭了、、
本文通过一道具体题目,介绍了从基础算法逐步升级到高级算法的过程,包括30分的基本解法及代码实现,进而深入探讨了更高分的解题思路,如NNT+数位dp等,并给出了一种复杂度较高的线段树解法。

853

被折叠的 条评论
为什么被折叠?



