好慌啊 0分??
T1
感觉是组合数,不知道对不对。
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #include<queue> #include<cmath> #include<ctime> using namespace std; const int P=1e9+7; long long n,k,ans=1; int main() { freopen("cube.in","r",stdin); freopen("cube.out","w",stdout); scanf("%lld%lld",&n,&k); int x; for(int i=1;i<=n;i++) scanf("%d",&x); for(int i=k+1;i<=n;i++) ans=(ans*i)%P; for(int i=2;i<=(n-k);i++) ans=(ans*i)%P; cout<<ans<<' '; return 0; }
完了组合数用错了,应该用逆元的。
思路:
其实就是说,在n个位置中,找出K个与原来不同的(1或0两种)。
组合数公式n! / k!(n-k)! 因为数比较大,如果先取模再除 是不对的。
用乘法逆元,/x %p等价于 *x^P-2 .
也可以分解质因数,不知道哪根筋抽了,这都没想到。
T2
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #include<queue> #include<cmath> using namespace std; const int N=1e5+100; int n,m,q; struct node{ int x,y; int z; }a[N],ask[N]; int f[N],tot; int find(int x) { while(x!=f[x]) x=f[x]=f[f[x]]; return x; } bool cmp(node u,node v) { return u.z>v.z;} bool fan(node u,node v) { return u.y<v.y;} int main() { freopen("warehouse.in","r",stdin); freopen("warehouse.out","w",stdout); scanf("%d%d%d",&n,&m,&q); for(int i=1;i<=m;i++) scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z); for(int i=1;i<=q;i++) scanf("%d",&ask[i].z),ask[i].y=i; sort(a+1,a+1+n,cmp);sort(ask+1,ask+1+q,cmp); for(int i=1;i<=n;i++) f[i]=i; tot=n;int ed=0,i=1,f1,f2; for(i=1;i<=q;i++) { while(a[ed+1].z>=ask[i].z) { ed++; f1=find(a[ed].x);f2=find(a[ed].y); if(f1!=f2) { f[f1]=f2;tot--; } } ask[i].x=tot; } sort(ask+1,ask+q+1,fan); for(int i=1;i<=q;i++) printf("%d ",ask[i].x); return 0; }
应该写对了啊,0分。。。
和昨天的题差不多,建一个最大生成树,在合并的过程中更新答案。
T3
不会去重,甚至计数都不会。
这道题的确不简单,因为一个字符串可能会得到多次,
那我们就就想办法让这个字符串只得到一次,怎么操作那?
维护两个数组a[i][j](表示长度为i的前缀,后面再加j字符就会重复的字符串数量)
c[i][j](表示以j为开头,长度为i的字符串数量)
(因为我们只需要考虑,字符串长度,和是否重复)
最后把长度和为L的前缀和后缀字符根据乘法原理组合起来就是答案了。
但是!这样做有漏洞!!
原因是对于本来就是一个单词一部分的字符如coo,它能由co 前缀和 o后缀 组成,但我们却没有判定出co这个前缀。
a c拼起来的基础是那个合法串从一个位置 开始 前缀变成不合法的了
但是coo这个串,整个串都是合法的。
但是coo这个串,整个串都是合法的。