0.Codechef
Strange Matrix
http://www.codechef.com/problems/RRMATRIX
题意:求纵向分布,横向分布重合数字个数
思路:设重合的坐标为i,j,那么
(i-1)*m+j=(j-1)*n+i
(i-1)*m+(j-1)=(j-1)*n+(i-1)
(i-1)*(m-1)=(j-1)*(n-1)
i=(j-1)*(n-1)/(m-1)+1
特殊情况,m=1时答案为n,n=1时答案为m
然后直接看,枚举j-1从0到m-1的话,i的范围从1到n
那么满足的就是(n-1)和(m-1)约掉后剩下枚举j-1看能整除多少次。
求g=gcd(n-1,m-1),那么约分后的分母为(m-1)/g,那么枚举j-1能整除的次数为 (m-1)/((m-1)/g)+1
也就是 g+1.
Code: Strange Matrix.cpp
Chef and Segments
http://www.codechef.com/problems/CHMOD
题意:输入n个数字(n<=10w,num<=100),求区间积对某值取余
思路:100以内25个素数,设dp[maxn][25]分别记录每个数字质因数分解之后的幂
然后扫一遍,累加起来,查询的时候用快速幂取模ans*=Pow(prime[i],dp[r][i]-dp[l-1][i])%mod
当然其他的做法也有,可以用树状数组建25棵树,但是没什么必要吧.
Code: Chef and Segments.cpp
2.Codechef
Matchsticks
http://www.codechef.com/problems/MSTICK
题意:给出一列数表示火柴燃尽的时间,查询表示点某一段区间的火柴,问全部燃尽要多久
思路:对于查询区间先求最小值,然后求其余区间的最大值,他们的和就是答案;
当然还要考虑的一种情况是,查询区间的最大值和最小值的平均数也影响答案.
Code: Matchsticks.cpp
3.CSU
Last digit
http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1347
题意: 求f(n,k)=(1^k+2^k+...+n^k)%10 n,k<=10^9
思路: 对于k,直接取 k=k%euler(10)+euler(10)=k%4+4就ok,不解释
对于n, 可以取 10 个一组,f(n,k)=(n/10)*f(10,k)+f(n%10,k)
Rectangular Queries
http://www.codechef.com/problems/RECTQUER
题意:给出矩阵的所有值(<=10),查询某矩形范围内出现不同数字的个数
思路:由于范围比较小,用dp[i][j][k]表示数字i,从(1,1)到(j,k)之间出现的次数;
查询矩形左上角(x1,y1)到右下角(x2,y2)间不同的数字个数
ans+=(dp[k][x2][y2]-(dp[k][x2][y1-1]+dp[k][x1-1][y2]-2*dp[k][x1-1][y1-1])-dp[k][x1-1][y1-1]>0)?1:0;
Code: Rectangular Queries.cpp
5.Codechef
Pairwise AND sum
http://www.codechef.com/problems/AND
题意:输入n个数字,求sum+=a[i]&a[j] (i<j) n<10^5 a[i]<=10^6
思路:转化成二进制,分别求第i位上累计有cnt个1,sum+=(cnt-1)*cnt/2*pow(2,i);
Code: Pairwise AND sum.cpp
6.Codechef
Chef and Gift
http://www.codechef.com/problems/CHGIFT1
题意:给出n个数字,现在往里面添加‘+’ ‘-’ ‘*’忽略优先级,求答案的最小值
思路:这题数据有好几种,做法是dp,用两个值记录当前的最大和最小值,扫一遍就ok
Code: Chef and Gift.cpp
7.Codechef
Online Shopping
http://www.codechef.com/problems/COUPON/
题意:n个要买的物品,在m家有不同的价格,在第j家店买了第i件物品时,第i+1件物品可以享受一定的折扣
问买这n个物品的最少花费
思路:用index和mi分别表示当前买的最后一件物品在第index家店,总的花费最小为mi
用滚动数组可以省内存,if(j==index) dp[0][j]=dp[1][j]+max(0,a[i][j]-b[i-1][j]);
else dp[0][j]=min(dp[1][index]+a[i][j],dp[1][j]+max(0,a[i][j]-b[i-1][j]));
Code: Online Shopping.cpp
8.Codechef
Matrix
http://www.codechef.com/problems/MATRIX2/
题意:输入一个n*m的01矩阵,计算这样的三元组的个数(i,j,h),对于所有的二元组(x,y)属于[1,h],if(y>=x)都要有a[i+x-1][j+y-1]等于1(貌似就是在说a[i+1][j]可以不必等于1)
思路:dp[i][j]用来表示当前处三元组中的h值
if(a[i][j]) dp[i][j]=min(dp[i-1][j-1],dp[i-1][j]);
else dp[i][j]=0;
Code: Matrix.cpp
9.Codechef
Chef and Pie
http://www.codechef.com/problems/CHXORR
题意:从给定的n个数里选出3个数,求这3个数异或的最大值(n<=2000)
思路:建一个二进制字典树,(n^2)*lg(30)的复杂度找到异或的最大值。
建树的过程看别人的代码的,不过还是很好奇为什么小数据竟然很容易挂。
10.Codechef
The Number Of Solutions
http://www.codechef.com/problems/CNTSOLS
题意:已知upper,d,m,N,求满足 x1^d+x2^d+x3^d≡m(mod N)的三元组(x1,x2,x3)的个数
思路:对于模N的情况下,找到x有解的可能=upper/N+(upper%N>=x)?1:0;
Strange Matrix
http://www.codechef.com/problems/RRMATRIX
题意:求纵向分布,横向分布重合数字个数
思路:设重合的坐标为i,j,那么
(i-1)*m+j=(j-1)*n+i
(i-1)*m+(j-1)=(j-1)*n+(i-1)
(i-1)*(m-1)=(j-1)*(n-1)
i=(j-1)*(n-1)/(m-1)+1
特殊情况,m=1时答案为n,n=1时答案为m
然后直接看,枚举j-1从0到m-1的话,i的范围从1到n
那么满足的就是(n-1)和(m-1)约掉后剩下枚举j-1看能整除多少次。
求g=gcd(n-1,m-1),那么约分后的分母为(m-1)/g,那么枚举j-1能整除的次数为 (m-1)/((m-1)/g)+1
也就是 g+1.
Code: Strange Matrix.cpp
Chef and Segments
http://www.codechef.com/problems/CHMOD
题意:输入n个数字(n<=10w,num<=100),求区间积对某值取余
思路:100以内25个素数,设dp[maxn][25]分别记录每个数字质因数分解之后的幂
然后扫一遍,累加起来,查询的时候用快速幂取模ans*=Pow(prime[i],dp[r][i]-dp[l-1][i])%mod
当然其他的做法也有,可以用树状数组建25棵树,但是没什么必要吧.
Code: Chef and Segments.cpp
2.Codechef
Matchsticks
http://www.codechef.com/problems/MSTICK
题意:给出一列数表示火柴燃尽的时间,查询表示点某一段区间的火柴,问全部燃尽要多久
思路:对于查询区间先求最小值,然后求其余区间的最大值,他们的和就是答案;
当然还要考虑的一种情况是,查询区间的最大值和最小值的平均数也影响答案.
Code: Matchsticks.cpp
3.CSU
Last digit
http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1347
题意: 求f(n,k)=(1^k+2^k+...+n^k)%10 n,k<=10^9
思路: 对于k,直接取 k=k%euler(10)+euler(10)=k%4+4就ok,不解释
对于n, 可以取 10 个一组,f(n,k)=(n/10)*f(10,k)+f(n%10,k)
(加强版:hdu 3369)
Code: csu1347.cpp
Rectangular Queries
http://www.codechef.com/problems/RECTQUER
题意:给出矩阵的所有值(<=10),查询某矩形范围内出现不同数字的个数
思路:由于范围比较小,用dp[i][j][k]表示数字i,从(1,1)到(j,k)之间出现的次数;
查询矩形左上角(x1,y1)到右下角(x2,y2)间不同的数字个数
ans+=(dp[k][x2][y2]-(dp[k][x2][y1-1]+dp[k][x1-1][y2]-2*dp[k][x1-1][y1-1])-dp[k][x1-1][y1-1]>0)?1:0;
Code: Rectangular Queries.cpp
5.Codechef
Pairwise AND sum
http://www.codechef.com/problems/AND
题意:输入n个数字,求sum+=a[i]&a[j] (i<j) n<10^5 a[i]<=10^6
思路:转化成二进制,分别求第i位上累计有cnt个1,sum+=(cnt-1)*cnt/2*pow(2,i);
Code: Pairwise AND sum.cpp
6.Codechef
Chef and Gift
http://www.codechef.com/problems/CHGIFT1
题意:给出n个数字,现在往里面添加‘+’ ‘-’ ‘*’忽略优先级,求答案的最小值
思路:这题数据有好几种,做法是dp,用两个值记录当前的最大和最小值,扫一遍就ok
Code: Chef and Gift.cpp
7.Codechef
Online Shopping
http://www.codechef.com/problems/COUPON/
题意:n个要买的物品,在m家有不同的价格,在第j家店买了第i件物品时,第i+1件物品可以享受一定的折扣
问买这n个物品的最少花费
思路:用index和mi分别表示当前买的最后一件物品在第index家店,总的花费最小为mi
用滚动数组可以省内存,if(j==index) dp[0][j]=dp[1][j]+max(0,a[i][j]-b[i-1][j]);
else dp[0][j]=min(dp[1][index]+a[i][j],dp[1][j]+max(0,a[i][j]-b[i-1][j]));
Code: Online Shopping.cpp
8.Codechef
Matrix
http://www.codechef.com/problems/MATRIX2/
题意:输入一个n*m的01矩阵,计算这样的三元组的个数(i,j,h),对于所有的二元组(x,y)属于[1,h],if(y>=x)都要有a[i+x-1][j+y-1]等于1(貌似就是在说a[i+1][j]可以不必等于1)
思路:dp[i][j]用来表示当前处三元组中的h值
if(a[i][j]) dp[i][j]=min(dp[i-1][j-1],dp[i-1][j]);
else dp[i][j]=0;
Code: Matrix.cpp
9.Codechef
Chef and Pie
http://www.codechef.com/problems/CHXORR
题意:从给定的n个数里选出3个数,求这3个数异或的最大值(n<=2000)
思路:建一个二进制字典树,(n^2)*lg(30)的复杂度找到异或的最大值。
建树的过程看别人的代码的,不过还是很好奇为什么小数据竟然很容易挂。
Code: Chef and Pie.cpp
10.Codechef
The Number Of Solutions
http://www.codechef.com/problems/CNTSOLS
题意:已知upper,d,m,N,求满足 x1^d+x2^d+x3^d≡m(mod N)的三元组(x1,x2,x3)的个数
思路:对于模N的情况下,找到x有解的可能=upper/N+(upper%N>=x)?1:0;
然后用O(N^3)跑一遍就ok (n<=40)