Codeforces Round #572 (Div. 2)
有助于理解倍增,ST算法
dp
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <cstring> 5 #include <string> 6 #include <algorithm> 7 #include <iostream> 8 using namespace std; 9 #define ll long long 10 11 const double eps=1e-8; 12 const ll inf=1e9; 13 const ll mod=1e9+7; 14 const int maxn=1e5+10; 15 16 int a[maxn],f[20][maxn],candy[20][maxn]; 17 18 int main() 19 { 20 int n,q,i,j,k,l,nn,x,y; 21 scanf("%d",&n); 22 for (i=1;i<=n;i++) 23 scanf("%d",&f[0][i]); 24 25 nn=log(n+eps)/log(2); 26 for (j=1;j<=nn;j++) 27 { 28 k=n-(1<<j)+1; 29 l=(1<<(j-1)); 30 for (i=1;i<=k;i++) 31 { 32 f[j][i]=(f[j-1][i]+f[j-1][i+l])%10; 33 candy[j][i]=candy[j-1][i]+candy[j-1][i+l]+(f[j-1][i]+f[j-1][i+l]>=10); 34 } 35 } 36 37 scanf("%d",&q); 38 while (q--) 39 { 40 scanf("%d%d",&x,&y); 41 nn=log(y-x+1+eps)/log(2); 42 printf("%d\n",candy[nn][x]); 43 } 44 return 0; 45 }
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <cstring> 5 #include <string> 6 #include <algorithm> 7 #include <iostream> 8 using namespace std; 9 #define ll long long 10 11 const double eps=1e-8; 12 const ll inf=1e9; 13 const ll mod=1e9+7; 14 const int maxn=1e5+10; 15 16 int tot[maxn],candy[20][maxn]; 17 18 int main() 19 { 20 int n,q,i,j,k,l,m,nn,x,y,a; 21 scanf("%d",&n); 22 for (i=1;i<=n;i++) 23 { 24 scanf("%d",&a); 25 tot[i]=(tot[i-1]+a)%10; 26 } 27 28 nn=log(n+eps)/log(2); 29 for (j=1;j<=nn;j++) 30 { 31 k=n-(1<<j)+1; 32 l=(1<<(j-1)); 33 m=(1<<j); 34 for (i=1;i<=k;i++) 35 candy[j][i]=candy[j-1][i]+candy[j-1][i+l]+( (tot[i+m-1]-tot[i+l-1]+10)%10 + (tot[i+l-1]-tot[i-1]+10)%10 >= 10 ); 36 } 37 38 scanf("%d",&q); 39 while (q--) 40 { 41 scanf("%d%d",&x,&y); 42 nn=log(y-x+1+eps)/log(2); 43 printf("%d\n",candy[nn][x]); 44 } 45 return 0; 46 } 47
好好学习数学。。。
#define mul(x,y) (ll)x*y%p
优点:
1. 宏定义,在编译为汇编代码时,减少执行次数(国家集训队有一篇文章),运行时间减少
2. 不容易漏写
实测:156ms -> 140ms
学习其它代码:
数组统计不同相同数字的个数
三种写法
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <cstring> 5 #include <string> 6 #include <algorithm> 7 #include <iostream> 8 using namespace std; 9 #define ll long long 10 #define mul(x,y) (ll)x*y%p 11 12 const double eps=1e-8; 13 const ll inf=1e9; 14 const ll mod=1e9+7; 15 const int maxn=3e5+10; 16 17 ll a[maxn]; 18 19 int main() 20 { 21 ll n,p,k,i,j,sum=0; 22 scanf("%lld%lld%lld",&n,&p,&k); 23 for (i=1;i<=n;i++) 24 { 25 scanf("%lld",&j); 26 a[i]=(mul(mul(mul(j,j),j),j)-mul(k,j)+p)%p; 27 } 28 sort(a+1,a+n+1); 29 a[n+1]=-1; 30 j=1; 31 for (i=1;i<=n;i++) 32 if (a[i]!=a[i+1]) 33 { 34 sum+=(i-j+1)*(i-j)/2; 35 j=i+1; 36 } 37 printf("%lld",sum); 38 return 0; 39 }
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <cstring> 5 #include <string> 6 #include <algorithm> 7 #include <iostream> 8 using namespace std; 9 #define ll long long 10 #define mul(x,y) (ll)x*y%p 11 12 const double eps=1e-8; 13 const ll inf=1e9; 14 const ll mod=1e9+7; 15 const int maxn=3e5+10; 16 17 ll a[maxn]; 18 19 int main() 20 { 21 ll n,p,k,i,j,sum=0; 22 scanf("%lld%lld%lld",&n,&p,&k); 23 for (i=1;i<=n;i++) 24 { 25 scanf("%lld",&j); 26 a[i]=(mul(mul(mul(j,j),j),j)-mul(k,j)+p)%p; 27 } 28 sort(a+1,a+n+1); 29 a[n+1]=-1; 30 for (i=1;i<=n;i++) 31 { 32 j=i; 33 while (a[i]==a[i+1]) 34 i++; 35 sum+=(i-j+1)*(i-j)/2; 36 } 37 printf("%lld",sum); 38 return 0; 39 } 40
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <cstring> 5 #include <string> 6 #include <algorithm> 7 #include <iostream> 8 using namespace std; 9 #define ll long long 10 #define mul(x,y) (ll)x*y%p 11 12 const double eps=1e-8; 13 const ll inf=1e9; 14 const ll mod=1e9+7; 15 const int maxn=3e5+10; 16 17 ll a[maxn]; 18 19 int main() 20 { 21 ll n,p,k,i,j,sum=0,cnt; 22 scanf("%lld%lld%lld",&n,&p,&k); 23 for (i=1;i<=n;i++) 24 { 25 scanf("%lld",&j); 26 a[i]=(mul(mul(mul(j,j),j),j)-mul(k,j)+p)%p; 27 } 28 sort(a+1,a+n+1); 29 30 cnt=1; 31 for (i=1;i<n;i++) 32 if (a[i]==a[i+1]) 33 cnt++; 34 else 35 sum+=cnt*(cnt-1)/2,cnt=1; 36 sum+=cnt*(cnt-1)/2; 37 printf("%lld",sum); 38 return 0; 39 } 40
末尾加上不同元素 or 添加末尾的处理/特判
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <cstring> 5 #include <string> 6 #include <algorithm> 7 #include <iostream> 8 using namespace std; 9 #define ll long long 10 #define mul(x,y) (ll)x*y%p 11 12 const double eps=1e-8; 13 const ll inf=1e9; 14 const ll mod=1e9+7; 15 const int maxn=3e5+10; 16 17 ll a[maxn]; 18 19 int main() 20 { 21 ll n,p,k,i,j,sum=0; 22 scanf("%lld%lld%lld",&n,&p,&k); 23 for (i=1;i<=n;i++) 24 { 25 scanf("%lld",&j); 26 a[i]=(mul(mul(mul(j,j),j),j)-mul(k,j)+p)%p; 27 } 28 sort(a+1,a+n+1); 29 for (i=1;i<=n;i++) 30 { 31 j=i; 32 while (i!=n && a[i]==a[i+1]) 33 i++; 34 sum+=(i-j+1)*(i-j)/2; 35 } 36 printf("%lld",sum); 37 return 0; 38 } 39
用map
容易写,相应地运行时间增加
#include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <string> #include <algorithm> #include <iostream> using namespace std; #define ll long long #include <map> #define mul(x,y) (ll)x*y%p const double eps=1e-8; const ll inf=1e9; const ll mod=1e9+7; const int maxn=3e5+10; map<int,int> ma; int main() { ll n,p,k,i,j,sum=0; scanf("%lld%lld%lld",&n,&p,&k); for (i=1;i<=n;i++) { scanf("%lld",&j); ma[ (mul(mul(mul(j,j),j),j)-mul(k,j)+p)%p ]++; } for (auto l:ma) sum+=l.second*(l.second-1)/2; printf("%lld",sum); return 0; }
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <cstring> 5 #include <string> 6 #include <algorithm> 7 #include <iostream> 8 using namespace std; 9 #define ll long long 10 #include <map> 11 #define mul(x,y) (ll)x*y%p 12 13 const double eps=1e-8; 14 const ll inf=1e9; 15 const ll mod=1e9+7; 16 const int maxn=3e5+10; 17 18 map<int,int> ma; 19 20 int main() 21 { 22 ll n,p,k,i,j,sum=0; 23 scanf("%lld%lld%lld",&n,&p,&k); 24 for (i=1;i<=n;i++) 25 { 26 scanf("%lld",&j); 27 ma[ (mul(mul(mul(j,j),j),j)-mul(k,j)+p)%p ]++; 28 } 29 30 for (pair<int,int> l:ma) 31 sum+=l.second*(l.second-1)/2; 32 33 printf("%lld",sum); 34 return 0; 35 }
一个脑洞:
同一个数字c有x个 x^2-x
y=a*x^2+b*x+c
对于二次函数,对于每次数字c的个数的改变,加上a
1+...+x=x^2+x
0+...+x-1=x^2-x
如 tot[c]++,sum+=tot[c]*a,
sum+=(b-a)*tot[c]+c。
1 #include <cstdio> 2 #include <cstdlib> 3 #include <cmath> 4 #include <cstring> 5 #include <string> 6 #include <algorithm> 7 #include <iostream> 8 using namespace std; 9 #define ll long long 10 #define mul(x,y) (ll)x*y%p 11 #include <map> 12 13 const double eps=1e-8; 14 const ll inf=1e9; 15 const ll mod=1e9+7; 16 const int maxn=3e5+10; 17 18 map<ll,ll> ma; 19 20 int main() 21 { 22 ll n,p,k,i,j,v,sum=0; 23 scanf("%lld%lld%lld",&n,&p,&k); 24 for (i=1;i<=n;i++) 25 { 26 scanf("%lld",&j); 27 v=(mul(mul(mul(j,j),j),j)-mul(k,j)+p)%p; 28 sum+=ma[v]++;///二次函数都可以这样写 29 ///每次获取ma[v]都需要时间,时间开销较大,如果是数组,则这个方法既便捷,运行时间也不会多多少 30 } 31 printf("%lld",sum); 32 return 0; 33 } 34