一周多上山实习只学了一些python,做题的手感差了好多QAQ,昨天晚上最开始电脑还更新重启折腾了好久,换成台式机做的,只做了一个题居然rating还涨了168,始料未及

前三个都是乱搞(第三个有一点贪心的意思

hdu5718Oracle

Accepts: 599
Submissions: 2576
Time Limit: 8000/4000 MS (Java/Others)
Memory Limit: 262144/262144 K (Java/Others)
问题描述
曾经有一位国王,统治着一片未名之地。他膝下有三个女儿。

三个女儿中最年轻漂亮的当属Psyche。她的父亲不确定她未来的命运,于是他来到Delphi神庙求神谕。

神谕可以看作一个不含前导零的正整数n n n。

为了得到真正的预言,他可以将n n n的各个数位重新排列,并将其分成两个不含前导零的正整数。

请你帮助他求出这两个正整数最大的和。如果不存在这样的两个正整数,输出"Uncertain".
输入描述
第一行一个整数T T T (1≤T≤10) (1 \le T \le 10) (1T10),代表数据组数。

接下来T T T行,每行一个正整数n n n (1≤n<1010000000) (1 \le n < 10 ^ {10000000}) (1n<1010000000)
输出描述
对于每组数据,输出一个整数表示最大的和。若不存在一种方案,输出"Uncertain".
输入样例
3
112
233
1
输出样例
22
35
Uncertain
Hint
对于第一组数据,最优方案是将112 112 112分成21 21 211 1 1,最大的和为21+1=22 21 + 1 = 22 21+1=22。

对于第二组数据,最优方案是将233 233 233分成2 2 233 33 33,最大的和为2+33=35 2 + 33 = 35 2+33=35。

对于第三组数据,显然无法将一个数位分成两部分。

建议使用效率较高的读入方式。
很容易想到拆出来一个最小的非零数+剩下的数是最终解,十分不懂为啥我的程序那么慢
#include <iostream>
#include<cstdio>
#include<cstring>
using namespace std;
char str[10000090];
int n,num[11];
int ans[10000090];
int main()
{
    scanf("%d",&n);
    while(n--)
    {
        scanf("%s",str);
        memset(num,0,sizeof(num));
        int tmp=0;
        int len=strlen(str);
        for(int i=0;i<len;i++)
        {
            if(str[i]!='0') tmp++;
          //  printf("stri=%c  i=%d\n",str[i],i);
            num[str[i]-'0']++;
        }
        //for(int i=0;i<=9;i++)printf("i=%d,num[i]=%d\n",i,num[i]);
        if(tmp<2)printf("Uncertain\n");
        else
        {
            for(int i=1;i<=9;i++)
            {
                if(num[i])
                {
                    tmp=i;
                    num[i]--;
                    break;
                }
            }
            int pos=0;
            for(int i=9;i>=0;i--)
            {
                while(num[i]--)
                    ans[pos++]=i;
            }
            pos--;
            ans[pos]+=tmp;
            if(ans[pos]>=10)
            {
                ans[pos-1]++;
                ans[pos]-=10;
            }
            for(int i=0;i<=pos;i++)printf("%d",ans[i]);
            puts("");
        }
    }
    return 0;
}

hdu5719arrange
问题描述
Cupid一不小心将爱情之箭射到了自己,他爱上了Psyche。

这引起了他的母亲Venus的注意。Venus将Psyche带到了一堆打乱的谷堆旁。

这儿共有n n n堆稻谷,编号为1 1 1n n n。Psyche需要将这些谷堆以某种顺序排列,设最终排在第i i i位的谷堆是Ai A_i Ai。

她得知了一些该排列的要求:

  1. 对于任意整数i∈[1,n] i \in [1,n] i[1,n]A1,A2,...,Ai A_1, A_2, ..., A_i A1,A2,...,Ai的最小值为Bi B_i Bi。

  2. 对于任意整数i∈[1,n] i \in [1,n] i[1,n]A1,A2,...,Ai A_1, A_2, ..., A_i A1,A2,...,Ai的最大值为Ci C_i Ci。

现在Psyche想知道,共有多少种合法的排列。由于答案可能很大,输出时对998244353 998244353 998244353取模。
输入描述
第一行,一个整数T T T (1≤T≤15) (1 \le T \le 15) (1T15),代表数据组数。

对于每组数据,第一行有一个整数n n n (1≤n≤105) (1 \le n \le 10 ^ 5) (1n105),代表排列大小。

第二行,n n n个整数,第i i i个整数为Bi B_i Bi (1≤Bi≤n) (1 \le B_i \le n) (1Bin)。

第三行,n n n个整数,第i i i个整数为Ci C_i Ci (1≤Ci≤n) (1 \le C_i \le n) (1Cin)
输出描述
输出T T T行,对于每组数据输出答案对998244353 998244353 998244353取模的结果。
输入样例
2
3
2 1 1
2 2 3
5
5 4 3 2 1
1 2 3 4 5
输出样例
1
0
Hint
对于第一组数据,只有一种合法的排列(2,1,3) (2,1,3) (2,1,3)。

对于第二组数据,没有合法的排列。
这题死于读错题,这些合法序列是没有重复的数字的,没有重复数字的!!!

所以就多了一个

if(c[i]-b[i]<i)flag=0;
那么乘进去的结果也少了    WA了一次由于LL
ans=(ans*(c[i]-b[i]-i+1)%mod); 
#include <iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define mod 998244353
int b[100009],c[100009],t,n;
int main()
{
    //freopen("cin.txt","r",stdin);
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(int i=0;i<n;i++)scanf("%d",&b[i]);
        for(int i=0;i<n;i++)scanf("%d",&c[i]);
        bool flag=1;
        long long ans=1;
        if(b[0]!=c[0])flag=0;
        for(int i=1;i<n&&flag;i++)
        {
            if(b[i]!=b[i-1]&&c[i]!=c[i-1])flag=0;
            if(c[i]-b[i]<i)flag=0;
            if(b[i]==b[i-1]&&c[i]==c[i-1])ans=(ans*(c[i]-b[i]-i+1)%mod);
          //  printf("i=%d,flag=%d\n",i,flag);
        }
       // cout<<flag<<endl;
        if(flag) printf("%I64d\n",ans);
        else printf("0\n");
    }
    return 0;
}
hdu5720wool
问题描述
黎明时,Venus为Psyche定下了第二个任务。她要渡过河,收集对岸绵羊身上的金羊毛。

那些绵羊狂野不驯,所以Psyche一直往地上丢树枝来把它们吓走。地上现在有n n n根树枝,第i i i根树枝的长度是ai a_i ai.

如果她丢的下一根树枝可以和某两根树枝形成三角形,绵羊就会被激怒而袭击她。

现在Psyche手中只有长度不小于L L L且不大于R R R的树枝。请你帮忙计算,她下一根可以丢多少种不同长度的树枝而不会把绵羊激怒呢?
输入描述
第一行,一个整数T(1≤T≤10) T (1 \le T \le 10) T(1T10),代表数据组数。

对于每组数据,第一行有三个整数n,L,R n,L,R n,L,R (2≤n≤105,1≤L≤R≤1018) (2 \le n \le 10 ^ 5, 1 \le L \le R \le 10 ^ {18}) (2n105,1LR1018)。

第二行,n n n个整数,第i i i个整数为ai a_i ai (1≤ai≤1018) (1 \le a_i \le 10 ^ {18}) (1ai1018),代表第i i i根树枝的长度。
输出描述
输出T T T行,对于每组数据,输出选取方式总数。
输入样例
2
2 1 3
1 1
4 3 10
1 1 2 4
输出样例
2
5
Hint
对于第一组数据,可以选用长度为2,3 2, 3 2,3的树枝。

对于第二组数据,可以选用长度为6,7,8,9,10 6, 7, 8, 9, 10 6,7,8,9,10的树枝。
昨天晚上做题的思路是:

扔出的树枝首先可以是大于最长的两个树枝长度之和,然后还可以是小于某两个树枝的长度差,但是这个长度差不能与其他的树枝组成三角形

暂时如果想不出反例的话,先看一下题解的做法:

考虑三角形三条边a,b,c (a \ge b) (ab)的关系ab<c,a+b>c,即 c \in (a-b,a+b) c(ab,a+b)

令加入的边为c c c,枚举所有边作为a a a的情况。对于所有可行的b b b,显然与a a a相差最小的可以让(ab,a+b)覆盖范围最大,所以可以贪心地选择不大于 a a的最大的 b b

于是我们可以先将边按长度排序,然后ai,ai+1建一条线段。线段并是不合法的部分。

将所有线段按左端点排序,按序扫描一遍,过程中统计答案即可
后一半没看懂,先说前面的意思:读入数组,排升序,(a[i]-a[i-1],a[i]+a[i-1])是对于有a[i]这个树枝的最长的能够组成三角形的长度,那么[l,r]的剩余部分是可选的长度,随着i的增大,这个区间是不断向右移动的,而且左区间端点一定是向右移动的,在一般的状态下,可行区间是分两段的L~a[i]-a[i-1]  a[i]+a[i-1]~R,我们把左侧区间长度添加到答案中,新的左端点更新为a[i]+a[i-1]+1,这个时候如果L>R循环停止。最终的答案再加上l-r的长度即可

这么看来自己之前的思路少情况啊

#include <iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int t,n;
long long l,r,a[100009];
int main()
{
    //freopen("cin.txt","r",stdin);
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%I64d%I64d",&n,&l,&r);
        for(int i=0;i<n;i++)scanf("%I64d",&a[i]);
        sort(a,a+n);
        long long lmin,rmax;
        long long ans=0;
        for(int i=1;i<n;i++)
        {
            lmin=a[i]-a[i-1]+1;
            rmax=a[i]+a[i-1]-1;
            if(rmax<l||lmin>r)continue;
            if(l<lmin)ans+=(lmin-l);
            l=rmax+1;
            if(l>r)break;
        }
        if(l<=r)   ans+=(r-l+1);
        printf("%I64d\n",ans);
    }
    return 0;
}