一周多上山实习只学了一些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) (1≤T≤10),代表数据组数。 接下来T T T行,每行一个正整数n n n (1≤n<1010000000) (1 \le n < 10 ^ {10000000}) (1≤n<10?10000000??)。
输出描述
对于每组数据,输出一个整数表示最大的和。若不存在一种方案,输出"Uncertain".
输入样例
3 112 233 1
输出样例
22 35 Uncertain
Hint
对于第一组数据,最优方案是将112 112 112分成21 21 21和1 1 1,最大的和为21+1=22 21 + 1 = 22 21+1=22。 对于第二组数据,最优方案是将233 233 233分成2 2 2和33 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 1到n n n。Psyche需要将这些谷堆以某种顺序排列,设最终排在第i i i位的谷堆是Ai A_i A?i??。 她得知了一些该排列的要求: 1. 对于任意整数i∈[1,n] i \in [1,n] i∈[1,n],A1,A2,...,Ai A_1, A_2, ..., A_i A?1??,A?2??,...,A?i??的最小值为Bi B_i B?i??。 2. 对于任意整数i∈[1,n] i \in [1,n] i∈[1,n],A1,A2,...,Ai A_1, A_2, ..., A_i A?1??,A?2??,...,A?i??的最大值为Ci C_i C?i??。 现在Psyche想知道,共有多少种合法的排列。由于答案可能很大,输出时对998244353 998244353 998244353取模。
输入描述
第一行,一个整数T T T (1≤T≤15) (1 \le T \le 15) (1≤T≤15),代表数据组数。 对于每组数据,第一行有一个整数n n n (1≤n≤105) (1 \le n \le 10 ^ 5) (1≤n≤10?5??),代表排列大小。 第二行,n n n个整数,第i i i个整数为Bi B_i B?i?? (1≤Bi≤n) (1 \le B_i \le n) (1≤B?i??≤n)。 第三行,n n n个整数,第i i i个整数为Ci C_i C?i?? (1≤Ci≤n) (1 \le C_i \le n) (1≤C?i??≤n)。
输出描述
输出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 a?i??. 如果她丢的下一根树枝可以和某两根树枝形成三角形,绵羊就会被激怒而袭击她。 现在Psyche手中只有长度不小于L L L且不大于R R R的树枝。请你帮忙计算,她下一根可以丢多少种不同长度的树枝而不会把绵羊激怒呢?
输入描述
第一行,一个整数T(1≤T≤10) T (1 \le T \le 10) T(1≤T≤10),代表数据组数。 对于每组数据,第一行有三个整数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}) (2≤n≤10?5??,1≤L≤R≤10?18??)。 第二行,n n n个整数,第i i i个整数为ai a_i a?i?? (1≤ai≤1018) (1 \le a_i \le 10 ^ {18}) (1≤a?i??≤10?18??),代表第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) (a≥b)的关系a?b<c,a+b>c,即
c \in (a-b,a+b) c∈(a?b,a+b)。
令加入的边为c c c,枚举所有边作为a
a a的情况。对于所有可行的b
b b,显然与a
a a相差最小的可以让(a?b,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; }