A:简单的贪心,删去最左边的0即可,没有0删任意一个。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<vector>
#include<queue>
#include<math.h>
#include<string>
#include<map>
#include<set>
#include<iostream>
using namespace std;
typedef long long ll;
const int inf=1<<29;
char str[100010];
int main()
{
scanf("%s",str);
int flag=0,pos;
for(int i=0;str[i];i++){
if(str[i]=='0'){
pos=i;
flag=1;
break;
}
}
if(flag){
for(int i=0;str[i];i++){
if(i==pos) continue;
printf("%c",str[i]);
}
puts("");
}else{
printf("%s\n",str+1);
}
}
B:先预处理一个简单的dp,dp[i][j][k]表示i位以j开头包含k个幸运数字的数的个数,这样就很容易快速统计出1-m中包含k个幸运数字的数有几个,枚举k,dfs求一下其余6人的组合。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<vector>
#include<queue>
#include<math.h>
#include<string>
#include<map>
#include<set>
#include<iostream>
using namespace std;
typedef long long ll;
const int inf=1<<29;
#define mod 1000000007
ll dp[12][12][12];
int bit[12];
int solve(int n,int m)
{
int t=m,kk=0,cnt=0;
while(t){
bit[++kk]=t%10;
if(bit[kk]==4||bit[kk]==7) cnt++;
t/=10;
}
int sum=0;
if(cnt==n) sum++;
if(n==0) sum--;
for(int i=kk;i>0;i--){
for(int j=0;j<bit[i];j++){
sum+=dp[i][j][n];
}
if(bit[i]==4||bit[i]==7) n--;
if(n<0) break;
}
return sum;
}
int vis[12];
int dfs(int n,int p,int m)
{
if(p>=6) return 1;
ll ans=0;
for(int i=0;i<=n;i++){
ll sum=solve(i,m)-vis[i];
if(sum<=0)continue;
vis[i]++;
sum*=dfs(n-i,p+1,m);
sum%=mod;
ans+=sum;
ans%=mod;
vis[i]--;
}
return ans;
}
int main()
{
dp[0][0][0]=1;
for(int i=0;i<=9;i++)
for(int j=0;j<=9;j++){
for(int k=0;k<=9;k++){
for(int p=0;p<=9;p++){
if(p==4||p==7)
dp[i+1][p][k+1]+=dp[i][j][k];
else
dp[i+1][p][k]+=dp[i][j][k];
}
}
}
int m;
scanf("%d",&m);
ll ans=0;
for(int i=1;i<=9;i++){
ll sum=solve(i,m);
if(sum==0) continue;
sum*=dfs(i-1,0,m);
sum%=mod;
ans+=sum;
ans%=mod;
}
printf("%I64d\n",ans);
}
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<vector>
#include<queue>
#include<math.h>
#include<string>
#include<map>
#include<set>
#include<iostream>
using namespace std;
typedef long long ll;
const int inf=1<<29;
#define mod 1000000007
int a[100010];
vector<int> e;
ll power(ll t,int n)
{
ll ans=1;
while(n){
if(n%2){
ans*=t;
ans%=mod;
}
n/=2;
t*=t;
t%=mod;
}
return ans;
}
int main()
{
int n;
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%d",&a[i]);
sort(a,a+n);
int Max=a[n-1];
ll ans=0;
for(int i=1;i<=Max;i++){
e.clear();
for(int j=1;j*j<=i;j++){
if(i%j==0) {
e.push_back(j);
if(i/j!=j) e.push_back(i/j);
}
}
e.push_back(inf);
sort(e.begin(),e.end());
int t=-1;
ll sum=1;
for(int j=1;j<(int)e.size();j++){
int left=0,right=n-1,mid,pos=-1;
while(left<=right){
mid=(left+right)>>1;
if(a[mid]<e[j]){
left=mid+1;
pos=mid;
}else
right=mid-1;
}
if(j==e.size()-1)
sum*=(power(j,pos-t)-power(j-1,pos-t)+mod)%mod;
else
sum*=power(j,pos-t);
sum%=mod;
t=pos;
}
ans=(ans+sum)%mod;
}
printf("%I64d\n",ans);
}
E:看到对整个子树的操作,很容易想到dfs序转化为线性,线段树维护区间操作。对于本题,转化为线性后在进行dfs遍历,遍历到节点u,对其相关的子树操作进行区间覆盖,回溯的时候撤销覆盖,那么ans[u]的值就等于遍历到u时线段树中被覆盖的节点数-1
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<vector>
#include<queue>
#include<math.h>
#include<string>
#include<map>
#include<set>
#include<sstream>
using namespace std;
#define N 100010
#define M tree[u]
#define ML tree[u*2]
#define MR tree[u*2+1]
vector<int> e[N], V[N];
int begin[N], end[N], t;
void dfs(int u, int pre) {
begin[u] = ++t;
for (int i = 0; i < (int) e[u].size(); i++) {
int v = e[u][i];
if (v == pre)
continue;
dfs(v, u);
}
end[u] = t;
}
struct Seg {
struct node {
int l, r;
int cnt, cover;
} tree[N * 4];
void init(int u, int l, int r) {
M.l = l, M.r = r;
M.cover = M.cnt = 0;
if (l == r)
return;
int mid = (l + r) >> 1;
init(u * 2, l, mid);
init(u * 2 + 1, mid + 1, r);
}
void push_up(int u){
if(M.cover) M.cnt=M.r-M.l+1;
else M.cnt=ML.cnt+MR.cnt;
}
void update(int u,int l,int r,int val){
if(M.l>=l&&M.r<=r){
M.cover+=val;
if(M.cover) M.cnt=M.r-M.l+1;
else{
if(M.l==M.r) M.cnt=0;
else M.cnt=ML.cnt+MR.cnt;
}
return;
}
if(ML.r>=l) update(u*2,l,r,val);
if(MR.l<=r) update(u*2+1,l,r,val);
push_up(u);
}
} seg;
int ans[N];
void solve(int u, int pre) {
for(int i=0;i<(int)V[u].size();i++){
seg.update(1,begin[V[u][i]],end[V[u][i]],1);
}
if(!V[u].empty()){
seg.update(1,begin[u],end[u],1);
}
ans[u]=seg.tree[1].cnt;
if(ans[u]) ans[u]--;
for (int i = 0; i < (int) e[u].size(); i++) {
int v = e[u][i];
if (v == pre)
continue;
solve(v, u);
}
for (int i = 0; i < (int) V[u].size(); i++) {
seg.update(1, begin[V[u][i]], end[V[u][i]], -1);
}
if (!V[u].empty()) {
seg.update(1, begin[u], end[u], -1);
}
}
int main() {
int n, m, x, y;
scanf("%d%d", &n, &m);
for (int i = 1; i < n; i++) {
scanf("%d%d", &x, &y);
e[x].push_back(y);
e[y].push_back(x);
}
for (int i = 0; i < m; i++) {
scanf("%d%d", &x, &y);
V[x].push_back(y);
V[y].push_back(x);
}
t = 0;
dfs(1, 1);
seg.init(1, 1, n);
solve(1, 1);
for(int i=1;i<=n;i++)
printf("%d ",ans[i]);
}