5道
K HDU 5774
直接贴过来模拟
出现的次数
#include<stdio.h> #include<algorithm> #include<stdlib.h> #include<cstring> #include<string> #include<cmath> #include<vector> #include<queue> #include<map> #include<iterator> #include<stack> using namespace std; #define ll __int64 #define MAXN 200010 #define inf 2000000007 #define mod 1000000007 char z[150][35]={"Cleveland Cavaliers", "Golden State Warriors", "San Antonio Spurs", "Miami Heat", "Miami Heat", "Dallas Mavericks", "L.A. Lakers", "L.A. Lakers", "Boston Celtics", "San Antonio Spurs", "Miami Heat", "San Antonio Spurs", "Detroit Pistons", "San Antonio Spurs", "L.A. Lakers", "L.A. Lakers", "L.A. Lakers", "San Antonio Spurs", "Chicago Bulls", "Chicago Bulls", "Chicago Bulls", "Houston Rockets", "Houston Rockets", "Chicago Bulls", "Chicago Bulls", "Chicago Bulls", "Detroit Pistons", "Detroit Pistons", "L.A. Lakers", "L.A. Lakers", "Boston Celtics", "L.A. Lakers", "Boston Celtics", "Philadelphia 76ers", "L.A. Lakers", "Boston Celtics", "L.A. Lakers", "Seattle Sonics", "Washington Bullets", "Portland Trail Blazers", "Boston Celtics", "Golden State Warriors", "Boston Celtics", "New York Knicks", "L.A. Lakers", "Milwaukee Bucks", "New York Knicks", "Boston Celtics", "Boston Celtics", "Philadelphia 76ers", "Boston Celtics", "Boston Celtics", "Boston Celtics", "Boston Celtics", "Boston Celtics", "Boston Celtics", "Boston Celtics", "Boston Celtics", "St. Louis Hawks", "Boston Celtics", "Philadelphia Warriors", "Syracuse Nats", "Minneapolis Lakers", "Minneapolis Lakers", "Minneapolis Lakers", "Rochester Royals", "Minneapolis Lakers", "Minneapolis Lakers", "Baltimore Bullets", "Philadelphia Warriors" }; int main() { int t,ca; scanf("%d",&t); getchar(); ca=1; while(t--) { char s[35]; gets(s); int cnt=0; for(int i=0;i<70;i++) if(strcmp(z[i],s)==0) cnt++; printf("Case #%d: %d ",ca++,cnt); } return 0; }
L t组样例 n n个数 HDU 5775
输出 i 出现的最左边的位子与最右边的位子的距离
显然 大 i 只能往右走 小的往左 最左边的位子就是 当前位子 或者i 最右边就是查询右边有多少个数比他小或者当前位子
多少个比他小 线段树维护一下
#include<stdio.h> #include<algorithm> #include<stdlib.h> #include<cstring> #include<string> #include<cmath> #include<vector> #include<queue> #include<map> #include<iterator> #include<stack> using namespace std; #define ll __int64 #define MAXN 200010 #define inf 2000000007 #define mod 1000000007 int z[MAXN]; struct node { int l,r,w; }tree[MAXN<<2]; int l1[MAXN],r1[MAXN]; void Build(int l,int r,int a) { tree[a].l=l; tree[a].r=r; tree[a].w=0; if(l==r) return; int mid=(l+r)>>1; Build(l,mid,a<<1); Build(mid+1,r,a<<1|1); } void Update(int l,int r,int a1,int a) { if(l==r) { tree[a].w++; return ; } int mid=(l+r)>>1; if(a1<=mid) Update(l,mid,a1,a<<1); else Update(mid+1,r,a1,a<<1|1); tree[a].w=tree[a<<1].w+tree[a<<1|1].w; } int Ques(int l,int r,int a1,int b1,int a) { if(a1<=l&&r<=b1) return tree[a].w; int mid=(l+r)>>1; int ans=0; if(a1<=mid) ans+=Ques(l,mid,a1,b1,a<<1); if(b1>mid) ans+=Ques(mid+1,r,a1,b1,a<<1|1); return ans; } int main() { int t,ca; scanf("%d",&t); ca=1; while(t--) { int n; scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&z[i]); Build(1,n,1); for(int i=n;i>=1;i--) { l1[z[i]]=min(i,z[i]); int a; if(z[i]==1) a=0; else a=Ques(1,n,1,z[i]-1,1); r1[z[i]]=max(z[i],i+a); Update(1,n,z[i],1); } printf("Case #%d:",ca++); for(int i=1;i<=n;i++) printf(" %d",r1[i]-l1[i]); printf(" "); } return 0; }
A HDU 5763
t组样例 2个字符串
求第一串有多少个意思 如果第二个串出现的话就可以有2种意思
先kmp 处理一下有没有出现 然后dp
dp[i]=max(dp[i],dp[i-1]);
如果出现 dp[i]=max(dp[i],dp[i-1]+dp[i-len2]+1) %mod;
#include<stdio.h> #include<algorithm> #include<stdlib.h> #include<cstring> #include<string> #include<cmath> #include<vector> #include<queue> #include<map> #include<iterator> #include<stack> using namespace std; #define ll __int64 #define MAXN 200010 #define inf 2000000007 #define mod 1000000007 char s1[MAXN],s2[MAXN]; ll dp[MAXN]; void kmp(char x[],int m,int next[]) { int i,j; j=next[0]=-1; i=0; while(i<m) { while(j!=-1&&x[i]!=x[j]) j=next[j]; next[++i]=++j; } } int nex[MAXN]; bool vis[MAXN]; int main() { int t,ca; scanf("%d",&t); ca=1; while(t--) { memset(vis,0,sizeof(vis)); memset(dp,0,sizeof(dp)); memset(nex,-1,sizeof(nex)); scanf("%s%s",s1,s2); int len2=strlen(s2); int len1=strlen(s1); kmp(s2,len2,nex); int i,j; i=j=0; int ans=0; while(i<len1) { while(j!=-1&&s1[i]!=s2[j]) j=nex[j]; i++; j++; if(j>=len2) { vis[i-1]=1; j=nex[j]; } } for(int i=0;i<len2;i++) dp[i]=vis[i]; for(int i=len2;i<len1;i++) { if(vis[i]) dp[i]=(dp[i-1]+dp[i-len2]+1)%mod; else dp[i]=dp[i-1]; } printf("Case #%d: %I64d ",ca++,(dp[len1-1]+1)%mod); } return 0; }
J HDU 5773
t 组样例
n n 个数
求出最长上升子序列 0可以变成任何整数 严格上升
前面有多少个0 这个数可以减少多少 然后求最长上升子序列 nlogn
加上0的个数 有点不理解的 不过好像也很对
#include<stdio.h> #include<algorithm> #include<stdlib.h> #include<cstring> #include<string> #include<cmath> #include<vector> #include<queue> #include<map> #include<iterator> #include<stack> using namespace std; #define ll __int64 #define MAXN 200010 #define inf 2000000007 #define mod 1000000007 int z[MAXN]; int dp[MAXN]; int sum[MAXN]; bool vis[MAXN]; int main() { int t,ca; scanf("%d",&t); ca=1; while(t--) { int n; scanf("%d",&n); memset(dp,0,sizeof(dp)); memset(sum,0,sizeof(sum)); memset(vis,0,sizeof(vis)); for(int i=1;i<=n;i++) { scanf("%d",&z[i]); if(z[i]==0) { sum[i]=sum[i-1]+1; vis[i]=1; } else sum[i]=sum[i-1]; z[i]=z[i]-sum[i]; } int ans=sum[n]; dp[0]=-inf; int cnt=0; for(int i=1;i<=n;i++) { if(vis[i]==1) continue; if(z[i]>dp[cnt]) dp[++cnt]=z[i]; else { int ind=lower_bound(dp,dp+cnt+1,z[i])-dp; dp[ind]=z[i]; } } ans +=cnt; printf("Case #%d: %d ",ca++,ans); } return 0; }
E HDU 5768
数学依旧难
t t组样例 n 个条件 l r
求满足 l ~r 能被7整除 然后满足条件的
pi ai 不能是%pi = ai
这B 显然是CRT然而并不会 其实CRT都忘记了 逆原都只会快速幂的了
GG
0~1<<n
容斥 奇加偶减 其实是要反一下的的
快速加法 然后求的结果也不是 r/ans的 要换个式子
#include<stdio.h> #include<algorithm> #include<stdlib.h> #include<cstring> #include<string> #include<cmath> #include<vector> #include<queue> #include<map> #include<iterator> #include<stack> using namespace std; #define ll __int64 #define MAXN 200010 #define inf 2000000007 #define mod 1000000007 int z[MAXN],m[MAXN],s[MAXN]; int n; ll Quick(ll a,ll b,ll c) //快速幂 { ll ans=1; a=a%c; while(b>0) { if(b&1) ans = (ans *a)%c; b>>=1; a=(a*a)%c; } return ans; } ll gao(ll a,ll r,ll p) //求结果 { return (a-r)/p; } ll add(ll a,ll b,ll c) //快速加法 { ll ans=0; a=a%c; while(b>0) { if(b&1) ans = (ans +a)%c; b>>=1; a=(a+a)%c; } return ans; } ll CRT(ll l,ll r)//z中国剩余定理 { ll M=1; ll ans=0; for(int i=0;i<=n;i++) if(s[i]) M*=z[i]; //printf("%I64d ",M); for(int i=0;i<=n;i++) { if(s[i]) { // printf("1 "); ll ni; ll Mi=M/z[i]; ni = Quick(Mi,z[i]-2,z[i]); ni=(ni%z[i]+z[i])%z[i]; ans =(ans+add(add(Mi,ni,M),m[i],M)%M+M)%M; } } if(ans<0) ans += M; //printf("%I64d %I64d ",ans,M); ll ret= gao(r+M,ans,M)-gao(l-1+M,ans,M); // printf("%I64d ",ret); return ret; } int main() { int t,ca; scanf("%d",&t); ca=1; while(t--) { ll l,r; scanf("%d%I64d%I64d",&n,&l,&r); for(int i=0;i<n;i++) scanf("%d%d",&z[i],&m[i]); memset(s,0,sizeof(s)); s[n]=1; z[n]=7; m[n]=0; int len=1<<n; ll ans=0; for(int i=0;i<len;i++) { int a=i; int k=0; for(int j=0;j<n;j++) { s[j]=0; if((1<<j)&a) s[j]=1; k=k+s[j]; } k=k & 1 ?-1:1; ans += 1ll *k *CRT(l,r); //printf("%I64d ",ans); } printf("Case #%d: %I64d ",ca++,ans); } return 0; }