【tyvj五月有奖赛 暨Loi 55 Round #1】
解题报告:
傻逼错误天天犯QAQ
第一题:简单DP,f[i][j]表示第 i 道题选 j 的最大得分,可以从f[i-1][j-1],f[i-1][j],f[i-1][j+1]转移过来,其实是可以滚动数组优化空间的,不过懒得弄了=。=反正能过
1 //TYVJ A 2 #include<vector> 3 #include<cstdio> 4 #include<cstdlib> 5 #include<cstring> 6 #include<iostream> 7 #include<algorithm> 8 #define rep(i,n) for(int i=0;i<n;++i) 9 #define F(i,j,n) for(int i=j;i<=n;++i) 10 #define D(i,j,n) for(int i=j;i>=n;--i) 11 using namespace std; 12 13 int getint(){ 14 int v=0,sign=1; char ch=getchar(); 15 while(ch<'0'||ch>'9') {if (ch=='-') sign=-1; ch=getchar();} 16 while(ch>='0'&&ch<='9') {v=v*10+ch-'0'; ch=getchar();} 17 return v*sign; 18 } 19 typedef long long LL; 20 const int N=500010,INF=~0u>>2; 21 /*******************template********************/ 22 int n,a[N],c[N],f[N][6]; 23 int main(){ 24 #ifndef ONLINE_JUDGE 25 freopen("input.txt","r",stdin); 26 // freopen("output.txt","w",stdout); 27 #endif 28 n=getint(); 29 char s[3]; 30 F(i,1,n){ 31 scanf("%s",s); 32 a[i]=s[0]-'A'+1; 33 c[i]=getint(); 34 } 35 F(i,1,n) F(j,1,4){ 36 f[i][j]=max(f[i-1][j-1],max(f[i-1][j],f[i-1][j+1]))+ 37 (j==a[i]?c[i]:0); 38 } 39 int ans=0; 40 F(j,1,4) ans=max(f[n][j],ans); 41 printf("%d\n",ans); 42 return 0; 43 }
第二题:数论题:求$$\sum_{i=1}^n \sum_{j=1}^m [gcd(i,j)是无平方因子的数]*gcd(i,j)$$
昂……蒟蒻实在太弱了就爆零了= =
UPD:2015年5月1日 22:18:17
题解:http://pan.baidu.com/s/1eQvTApW
写法是学习的hzwer的……因为$n\leq 150W$所以其实筛出μ以后直接暴算g即可……反正O(nlogn)是不会爆的0.0
1 //TYVJ B 2 #include<cmath> 3 #include<vector> 4 #include<cstdio> 5 #include<cstdlib> 6 #include<cstring> 7 #include<iostream> 8 #include<algorithm> 9 #define rep(i,n) for(int i=0;i<n;++i) 10 #define F(i,j,n) for(int i=j;i<=n;++i) 11 #define D(i,j,n) for(int i=j;i>=n;--i) 12 using namespace std; 13 14 int getint(){ 15 int v=0,sign=1; char ch=getchar(); 16 while(ch<'0'||ch>'9') {if (ch=='-') sign=-1; ch=getchar();} 17 while(ch>='0'&&ch<='9') {v=v*10+ch-'0'; ch=getchar();} 18 return v*sign; 19 } 20 typedef long long LL; 21 const int N=1500010,INF=~0u>>2; 22 /*******************template********************/ 23 int prime[N],tot,n,m,f[N],mu[N]; 24 LL g[N]; 25 bool check[N]; 26 void getmu(int n){ 27 mu[1]=1; 28 F(i,2,n){ 29 if (!check[i]){ 30 prime[++tot]=i; 31 mu[i]=-1; 32 } 33 F(j,1,tot){ 34 if (i*prime[j]>n) break; 35 check[i*prime[j]]=1; 36 if (i%prime[j]==0){ 37 mu[i*prime[j]]=0; 38 break; 39 }else mu[i*prime[j]]=-mu[i]; 40 } 41 } 42 F(i,1,n) if (mu[i]) f[i]=i; 43 F(i,1,n) if (f[i]) 44 for(int j=1;j*i<=n;j++) 45 g[j*i]+=f[i]*mu[j]; 46 F(i,1,n) g[i]+=g[i-1]; 47 } 48 int main(){ 49 #ifndef ONLINE_JUDGE 50 freopen("B.in","r",stdin); 51 // freopen("output.txt","w",stdout); 52 #endif 53 int T=getint(); 54 getmu(1500000); 55 while(T--){ 56 n=getint(); m=getint(); 57 LL ans=0; 58 if (n>m) swap(n,m); 59 for(int i=1,last;i<=n;i=last+1){ 60 last=min(n/(n/i),m/(m/i)); 61 ans+=(g[last]-g[i-1])*(n/i)*(m/i); 62 } 63 printf("%I64d\n",ans); 64 } 65 return 0; 66 } 67 //必须保证单次询问O(sqrt(N))的时间内搞定
第三题:询问到树上两点距离$\leq K$的点的个数,强制在线。
= =蒟蒻实在太弱,只能捡上白送的60分跑。
60分做法:$n\leq 1000$,所以$n^2$的做法即可,那么处理出来dist[i][j]即任意两点间的距离,每次查询O(n)枚举即可,因为是树上距离,所以以每个点为根dfs一次即可求出dist[i][j]。
第四题:太神了不会做,听说要用FWT?
第五题:经典毒瘤题= =(神犇们都说是大水题Orz)因为取模每次必然使数折半,所以每个数最多取模log(a[i])次,那么每个数可以视为一开始有log(a[i])的能量,每次取模能量-1,单点修改可以视为给这个数重新充能。
所以只要用线段树维护区间最大值(便于确定哪些数不用取模)和区间和,每次取模时在线段树上一路走到叶子进行修改,就可以AC啦~
我是SB:每次query之前忘记把ans清零了!!!!f**k,一句话爆零系列。
1 //TYVJ E 2 #include<vector> 3 #include<cstdio> 4 #include<cstdlib> 5 #include<cstring> 6 #include<iostream> 7 #include<algorithm> 8 #define rep(i,n) for(int i=0;i<n;++i) 9 #define F(i,j,n) for(int i=j;i<=n;++i) 10 #define D(i,j,n) for(int i=j;i>=n;--i) 11 using namespace std; 12 typedef long long LL; 13 LL getLL(){ 14 LL v=0,sign=1; char ch=getchar(); 15 while(ch<'0'||ch>'9') {if (ch=='-') sign=-1; ch=getchar();} 16 while(ch>='0'&&ch<='9') {v=v*10+ch-'0'; ch=getchar();} 17 return v*sign; 18 } 19 20 const int N=100010,INF=~0u>>2; 21 /*******************template********************/ 22 23 LL mx[N<<2],sum[N<<2],a[N],n,m; 24 #define L (o<<1) 25 #define R (o<<1|1) 26 #define mid (l+r>>1) 27 void maintain(int o,int l,int r){ 28 if (l==r) return; 29 mx[o]=max(mx[L],mx[R]); 30 sum[o]=sum[L]+sum[R]; 31 } 32 void build(int o,int l,int r){ 33 if (l==r) { 34 sum[o]=mx[o]=a[l]; 35 }else{ 36 build(L,l,mid); 37 build(R,mid+1,r); 38 maintain(o,l,r); 39 } 40 } 41 void update(int o,int l,int r,int pos,LL v){ 42 if (l==r) a[l]=mx[o]=sum[o]=v; 43 else{ 44 if (pos<=mid) update(L,l,mid,pos,v); 45 else update(R,mid+1,r,pos,v); 46 maintain(o,l,r); 47 } 48 } 49 int ql,qr; 50 void modify(int o,int l,int r,LL x){ 51 if (ql>r || qr<l) return; 52 if (mx[o]<x) return; 53 if (l==r) a[l]=mx[o]=sum[o]=a[l]%x; 54 else{ 55 modify(L,l,mid,x); 56 modify(R,mid+1,r,x); 57 maintain(o,l,r); 58 } 59 } 60 LL ans; 61 void query(int o,int l,int r){ 62 if (ql<=l && qr>=r) ans+=sum[o]; 63 else{ 64 if (ql<=mid) query(L,l,mid); 65 if (qr>mid) query(R,mid+1,r); 66 } 67 } 68 int main(){ 69 #ifndef ONLINE_JUDGE 70 freopen("E.in","r",stdin); 71 // freopen("output.txt","w",stdout); 72 #endif 73 n=getLL(); m=getLL(); 74 F(i,1,n) a[i]=getLL(); 75 build(1,1,n); 76 LL cmd,l,k,x; 77 F(i,1,m){ 78 cmd=getLL(); l=getLL(); k=getLL(); 79 if (cmd==1){ 80 ql=l; qr=k; ans=0; 81 query(1,1,n); 82 printf("%I64d\n",ans); 83 }else if (cmd==2){ 84 x=getLL(); 85 ql=l; qr=k; 86 modify(1,1,n,x); 87 }else{ 88 update(1,1,n,l,k); 89 } 90 } 91 return 0; 92 }