A.1-n两两相乘能得到多少个不同的数字?
解法:正解还不知道,此题可以直接O(n^2)预处理f[n],询问时查询即可
B.C(n,r),
x<=n<=y,0=<r<=n
中奇数个数
解法:
结论:C(n,r)为奇数的充要条件是n&r=r
结论:C(n,r),
0=<r<=n
中奇数个数为
2j
个,j为n的二进制中1的个数
由以上两个结论,可以得到此题的统计方法。先统计
0<=n<=y
的结果
将n表示成二进制,遇到1时讨论此位是1还是0,如果是0,那么后面的位数可以随意填充,因此需要预处理二进制前k位的组合数结果和。如果是1,那么继续往后移动。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <algorithm>
#include <queue>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define ll long long
#define ul unsigned long long
#define N maxn
using namespace std;
ll l,r;
ll Power(ll a,ll b){
ll ans=1ll;
for(ll i=0;i<b;i++) ans=ans*a;
return ans;
}
ll cal(ll x){
ll ans=0,xi=1,xx=x,i=0;
while(xx){
if(xx&1){
ans*=2; xi*=2;
ans+=Power(3,i);
}
i++,xx/=2;
}
return ans;
}
int main(){
//freopen("a.txt","r",stdin);
while(scanf("%lld%lld",&l,&r)!=EOF){
if(l==0&&r==0) break;
ll ansa=cal(r+1),ansb=cal(l);
printf("%llu\n",ansa-ansb);
}
return 0;
}
E.
k!(1<=k<=n)
中10的幂次不同的个数
解法:n/5即为答案。
拓展:x的幂次不同的个数为n/p,p为x中最大的素因子
F.求矩阵中的最长路和最短路,移动法则是只能向右下方移动
解法:有很明显的移动方向,dp即可解决
G.构造题。重点在通过不等关系判断等式的解。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <algorithm>
#include <queue>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define ll long long
#define N maxn
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 1000+10;
int t,n,m;
int a[maxn][maxn],ans[maxn][maxn];
void solve(){
for(int i=1;i<=n;i+=2){
for(int j=1;j<=m;j++){
a[i][j]=a[i][j]-ans[i-1][j-1]-ans[i-1][j]-ans[i-1][j+1];
}
if(i==n){
if(a[i][1]>=4) ans[i][1]=1,a[i][1]-=3;
if(a[i][2]-a[i][1]>=3) ans[i][2]=1,a[i][2]-=3;
for(int j=3;j<=m;j++){
if(a[i][j]-a[i][j-1]+ans[i][j-2]>=3) ans[i][j]=1,a[i][j]-=3;
}
continue;
}
if(a[i][1]>=4) ans[i][1]=1,a[i][1]-=3;
if(a[i][2]-a[i][1]>=3) ans[i][2]=1,a[i][2]-=3;
if(a[i+1][1]-a[i][1]>=3) ans[i+1][1]=1,a[i+1][1]-=3;
ans[i+1][2]=a[i][1]-ans[i][1]-ans[i][2]-ans[i+1][1];
if(ans[i+1][2]==1) a[i+1][2]-=3;
for(int j=3;j<=m;j++){
if(a[i][j]-a[i][j-1]+ans[i][j-2]+ans[i+1][j-2]>=3) ans[i][j]=1,a[i][j]-=3;
ans[i+1][j]=a[i][j-1]-ans[i][j-1]-ans[i][j-2]-ans[i][j]-ans[i+1][j-2]-ans[i+1][j-1];
if(ans[i+1][j]==1) a[i+1][j]-=3;
}
}
}
int main(){
//freopen("a.txt","r",stdin);
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
memset(ans,0,sizeof(ans));
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&a[i][j]);
solve();
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(ans[i][j]==1) printf("L"); else printf("-");
}
printf("\n");
}
}
return 0;
}
H.矩阵被若干加号形式覆盖,每个点有一个覆盖次数,求满足覆盖次数的加号分布。
解法:搜索。每次遇到覆盖一次的位置,将它作为加号中心,找到它的最远边界,作为加号长度,然后继续搜索下一个位置
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <algorithm>
#include <queue>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define ll long long
#define N maxn
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 100+10;
int t,n,m;
int ma[maxn][maxn],sum,can[maxn][maxn];
int ans,ansx,ansy;
bool dfs(int i,int j,int sum){
if(sum==0) return true;
if(i==n&&j==m) return false;
if(ans>=9&&sum!=0) return false;
int x=i,y=j+1;
if(y>m) x=i+1,y=1;
if(i!=1&&i!=n&&j!=1&&j!=m&&ma[i][j]==1){
int c=1;
while(i>=c&&i+c<=n&&j>=c&&j+c<=m&&ma[i-c][j]>0&&ma[i+c][j]>0&&ma[i][j-c]>0&&ma[i][j+c]>0){
ma[i-c][j]--,ma[i+c][j]--,ma[i][j-c]--,ma[i][j+c]--; c++; sum-=4;
}
c--;
if(c){
sum-=1; ma[i][j]=0;
if(dfs(x,y,sum)){
ans++;
if(ansx<i) { ansx=i,ansy=j; }
else if(ansx==i&&ansy<j) ansy=j;
return true;
}
ma[i][j]=1; sum+=1;
}
while(c){
ma[i-c][j]++,ma[i+c][j]++,ma[i][j-c]++,ma[i][j+c]++; c--; sum+=4;
}
}
return dfs(x,y,sum);
}
int main(){
//freopen("a.txt","r",stdin);
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
sum=0;
memset(can,0,sizeof(can));
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){
scanf("%d",&ma[i][j]);
sum+=ma[i][j];
if(i!=1&&i!=n&&j!=1&&j!=m){
if(ma[i][j]==1&&ma[i-1][j]>0&&ma[i+1][j]>0&&ma[i][j-1]>0&&ma[i][j+1]>0) can[i][j]=1;
}
}
ans=0,ansx=-1,ansy=-1;
dfs(1,1,sum);
printf("%d\n",ans);
printf("%d %d\n",ansx,ansy);
}
return 0;
}
I.匹配问题,拆点最大流解决。
J.m个定长等间距区间覆盖整个数轴,问1-n中每个点被覆盖1-m次的点个数
解法:定长等间距区间覆盖满足mod的性质。判断一个点是否被一区间覆盖,只要判断该点mod间距是否在该区间内,预处理mod b大于a的区间总和dp[b][a],对于k点只要加上所有的dp[b][k%b]即可
K.每天有一个选择得到一定利润,换选择需要付出代价,求最大利润
解法:简单O(n^3)dp
L.矩阵中每个数字是它的四条相邻边权值之和,矩阵边界权值为0。矩阵中只有一个数字未知,求该数字的值。
解法:求与该格子的曼哈顿距离,奇数加偶数减,结果即为所求