标签:res ++ 方式 就是 hellip get etc 大于 har
B,B:a*b+a+b=a*10b的位数+b。化简得知b+1=10b的位数。所以只有9,99,999……这样是可行的。
#include <bits/stdc++.h> using namespace std; const int maxn=4e5+10; typedef long long ll; ll n,m,ans; char l,r; char s[maxn]; int a[maxn]; int read(){ char c=getchar();int x=0,f=1; while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1; c=getchar();} while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘; c=getchar();} return x*f; } int work(int x) { int ans=0; while(x){ ans++; x/=10; } return ans; } int run(int x) { int vis=0; while(x){ if(x%10!=9) vis=1; x/=10; } if(vis==1) return 1; else return 0; } int main() { int T; T=read(); while(T--){ n=read(),m=read(); ll res=work(m); if(run(m)) res--; ll k=res*n; printf("%lld\n",k); } }
C
给出n,m,表示你可以用1到n的元素组装出m个元素构成的字符串,如m=4,a=【1,1,1,3】
现在给出要求,要求a,b两个数组,a数组不能下降,b数组不能上升,然后a的对应位置元素要小于等于b。
题解:
我们将b数组放过来看,就和a一样是不能下降,也就和a一样了,也就是2m长度的不下降的序列有多少个,直接dp
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=1e3+10; const int P=1000000007; ll DP[maxn][maxn]; int main() { int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;++i)DP[1][i]=1; for(int i=2;i<=2*m;++i){ for(int j=1;j<=n;++j){ for(int k=1;k<=j;++k){ DP[i][j]=(DP[i][j]+DP[i-1][k])%P; } } } ll ans=0; for(int i=1;i<=n;++i){ ans=(ans+DP[m][i])%P; } printf("%lld\n",ans); return 0; }
D
给出n个数组每个数组有m个元素(注意m很小),你每次可以选择任一两个数组,ai和aj,然后组成新数组,新数组的每个元素都是从对应的位置的连个数组中挑选最大的。
问求所有组装方法中,这个新数组的最小元素是最大化的。
题解:
首先我们可以用二分方法来二分出这个值是多少,那二分的判断机制是什么?
就是判断当前这个值(因为这个值是新数组元素最小的,所以其他元素就得大于等于它)
同时我们发现这个m很小,故我们可以用状态压缩来表示状态。
具体实现方式:
我们利用状态压缩来表示a数组中每个元素是否大于x,如果大于等于,该位置就是1
例如a(1 2 3 4 0)x=2,那么就算01110.
然后记录当前状态是第几行得到的(多个相同状态也无所谓,随着x的提高也就是二分,我们会选出最优的那个的)。
然后接下来开始匹配,首先是i|j==lim,也就是表明每个位置都是1,每个位置都有元素,然后判断这两个状态是否有数组提供。
#include<stdio.h> #define ri register int #define il inline const int M=300005; const int N=12; int p[N],id[M],a[M][N],n,m,o1,o2,lim; bool ck(const int&x){ ri i,j,res; for(i=0;i<=lim;++i) id[i]=0;//清空所有状态 for(i=1;i<=n;++i){ res=0; for(j=1;j<=m;++j) if(a[i][j]>=x) res|=p[j];//满足条件的状态压缩起来 id[res]=i;//记录这个状态是抽出第行得到的 } for(i=0;i<=lim;++i)//枚举i,j两个状态进行检查,是否可以抽出id[i]和id[j]以得到答案 for(j=i;j<=lim;++j)//j从i枚举,以免重复计算 if((i|j)==lim&&id[i]&&id[j]) return o1=id[i],o2=id[j],1; return 0; } il void ms(){//MidSearch 即二分现在最大最小的b int l=0,r=1e9,mid; while(l<=r) mid=l+r>>1,ck(mid)?l=mid+1:r=mid-1;//满足条件,说明还可能存在较大解 } int main(){ scanf("%d%d",&n,&m); for(ri i=1,j;i<=n;++i) for(j=1;j<=m;++j) scanf("%d",&a[i][j]); lim=(1<<m)-1; for(ri i=1;i<=m;++i) p[i]=1<<i-1;//常数优化 ms(),printf("%d %d\n",o1,o2);//输出任意一组满足条件的解即可 return 0; }
Educational Codeforces Round 80 (Rated for Div. 2)
标签:res ++ 方式 就是 hellip get etc 大于 har
原文地址:https://www.cnblogs.com/hgangang/p/12202461.html