// //

2019西安多校联训 Day4

   T1

  大水题!!难度简单,显然的贪心策略即可,but...

  思路:首先我们按与i点作战后活下来的士兵排序,然后

若当前剩余兵力足够直接减掉战斗死亡人数,如果不够就加

够再打它,但是!我们在考完试观察测试点时发现了这样一组

测试点:

  2

  7 4

  5 1

  emmm,这组测试点是什么意思呢??我们只需要4个人就可以

打下这座城市,但打这个城市的4个人中需要阵亡7人!(???喵喵喵???)

这就很尴尬了,当我们遇到这样的点时,我们只需凑够阵亡人数即可

不用管剩余人数(显然无人生还...)

 

T1-
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 struct node{
 4     long long x,y;
 5 }a[100010];
 6 long long n,mlast,ans;
 7 long long T;
 8 bool cmp(node p,node q){
 9     return (p.y-p.x)>(q.y-q.x); 
10 }
11 inline void solve(){
12     for(register int i=1;i<=n;i++){
13         if(a[i].y<a[i].x&&mlast<a[i].x){ans+=(a[i].x-mlast),mlast=0;continue;}
14         else if(a[i].y<a[i].x&&mlast>=a[i].x){mlast-=a[i].x;continue;} 
15         if(mlast>=a[i].y){
16             mlast-=a[i].x;
17             continue;
18         }
19         else if(mlast<a[i].y){
20             ans+=a[i].y-mlast;
21             mlast=a[i].y-a[i].x;
22         }
23     }
24 }
25 int main(){
26     scanf("%lld",&T);
27     while(T--){
28         memset(a,0,sizeof(a));
29         ans=0;mlast=0;
30         scanf("%lld",&n);
31         for(register int i=1;i<=n;i++) scanf("%lld%lld",&a[i].x,&a[i].y);
32         sort(a+1,a+n+1,cmp);
33         solve();
34         printf("%lld\n",ans);
35     }
36     return 0;
37 }
X国的军队

 

   T2

  这道题是一道数论题,对没有学过组合数同学非常不友好

(当然对我这种学过组合数但是只会杨辉三角的人也不友好....)

难度中等,因为有规律鸭

  思路:首先我们需要知晓组合数的定义如下图

    

  此乃组合数,那我们可以好好看题了,根据二项式定理我们知道

C0n+C1n+C2n+...Cnn=2^n;这是无比显然的,但平方过后规律产生了

变化,由作业帮可得(Cn0)^2+(Cn1)^2+(Cn2)^2+...+(Cnn)^2=(2n!)/(n!)^2

由这个式子再加上组合数的一些定理可得(反正我是不会证的)

  ans=(2n)!*(n!)^(mod-2)%mod

  其中(n!)^(mod-2)即为(n!)^2在mod下的逆元,所以除法变为乘法

然后在我们了解了公式之后打一个(2n)!的表,然后每次算完%一下mod

然后套个快速幂即可,数据过多可以再套个快读快写

 

T2-
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 long long n,T;
 4 const long long modd=1e9+7;
 5 long long dis[2000010],x[2000010];
 6 long long ans,ak,ac,wa;
 7 long long ksm(long long a, long long b, long long p){
 8      long long ret=1;
 9      while(b){
10          if(b%2)ret=(ret*a)%p;
11          a=(a*a)%p;
12          b=b>>1;
13      }
14      return ret;
15 }
16 inline int read(){
17     int X=0; bool flag=1; char ch=getchar();
18     while(ch<'0'||ch>'9') {if(ch=='-') flag=0; ch=getchar();}
19     while(ch>='0'&&ch<='9') {X=(X<<1)+(X<<3)+ch-'0'; ch=getchar();}
20     if(flag) return X;
21     return ~(X-1);
22 }
23 inline int write(long long X){
24     if(X<0) {putchar('-'); X=~(X-1);}
25     int s[20],top=0;
26     while(X) {s[++top]=X%10; X/=10;}
27     if(!top) s[++top]=0;
28     while(top) putchar(s[top--]+'0');
29 }
30 int main(){
31     T=read();
32     dis[0]=x[0]=1;
33     for(register int i=1;i<=2000000;i++) dis[i]=dis[i-1]*i%modd;
34     while(T--)
35     {
36         n=read();
37         wa=ksm(dis[n],modd-2,modd);
38         ans=dis[2*n]*wa%modd*wa%modd;
39         write(ans);
40         putchar('\n');
41     }
42     return 0;
43 }
排列组合

 

   T3

  考试时我竟然想用线段树做!!(快停止这危险的想法),难度中上

其实本题正解是带有dp色彩的模拟...

  思路:首先咱们可以发现一个回文字符串的性质,假设咱们有一字符串长度>=3

假设它左右端点的字符相同,那显然内侧也是一个回文串,其次我们很显然的发现只

有一个字符的串是回文串,然后长度为2的字符串只需要特判一下就可以确定是否为

回文串了,验证回文串算法get√

  其次我们为什么称这道题为带有dp色彩的模拟呢?显然我们可以先O(n)处理一遍长度为1和长度为2的字符串,然后我即可找到dp式 dp[i][j]=dp[i][j-1]+dp[i+1][j]-dp[i+1][j-1];

非常优秀!而dp结束后我们只需要再判断整合后的字符串是否满足回文串即可

T3-
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 long long T,n;
 4 int l,r;
 5 int a[5010][5010];
 6 bool vis[5010][5010];
 7 char s[100010];
 8 bool check(int L,int R){
 9     if(vis[L][R]) return true;
10     else if(s[L]==s[R]) return check(L+1,R-1); 
11     return false;
12 }
13 int main(){
14     cin>>s+1;
15     int len=strlen(s+1);
16     scanf("%lld",&T);
17     for(register int i=1;i<=len;i++){
18         vis[i][i]=true;
19         a[i][i]++;
20         a[i][i+1]=2;
21         if(s[i]==s[i+1]) a[i][i+1]++,vis[i][i+1]=true;
22     }
23     for(register int i=3;i<=len;i++){
24         for(register int l=1;l+i-1<=len;l++){
25             int r=l+i-1;
26             a[l][r]=a[l][r-1]+a[l+1][r]-a[l+1][r-1];
27             if(check(l,r)) a[l][r]++,vis[l][r]=true;
28         }
29     }
30     while(T--){
31         int num1,num2;
32         scanf("%d%d",&l,&r);
33         printf("%d\n",a[l][r]);
34     }
35     return 0;
36 }
回文

  end;

 

posted @ 2019-06-13 16:21  Zafkiel  阅读(231)  评论(4编辑  收藏  举报
Live2D //博客园自带,可加可不加