一直不在状态……
想着各种事情……
A.
正常的方法是预处理k!和inv(k!),然后每次询问O(1)。
然后某同学的方法是dp,O(n*m)也能过。
f(i,j,0)和f(i,j,1)吗?i<=n,j<=m,0和1分别代表是否已经选择F吗。
B.
对于a,是x的倍数,且不是y的倍数(其中p%x==0,y%x==0,p%y==0)
x乘上某个数,这个数除以z(z为不可以使用的约数的乘积,详见代码)为r(计算0~z-1)。
则对于b,是(p/x)的倍数
不好写。。。
时间复杂度:
预处理:k个质因数(<=6),2^k * 对应的大小(<=p)
约数的个数*(k+k)
还有更快的方法
题解:数论方式分析。
a=px+y
y*b=p的倍数
则b是p/y的倍数。
然后枚举y。
写得很快。。。
看群里还有使用mobius的,比赛时想过,但没想到。
对于数字a,b
gcd(a,p)=d
然后b为p/d的倍数即可。
1 #include2 #include 3 #include 4 #include 5 #include 6 #include 7 #include 8 using namespace std; 9 #define ll long long 10 11 const double eps=1e-8; 12 const ll inf=1e9; 13 const ll mod=1e9+7; 14 const int maxn=1e5+10; 15 16 ///2,3,5,7,11,13 17 18 struct node 19 { 20 ll g; 21 ///large to small 22 ll a[10],b[10]; 23 }f[maxn]; 24 25 ll zhi[maxn],zhi_cnt,maxv=1e5; 26 ll x[300],gx[300],y[130][maxn]; 27 bool vis[maxn],use[maxn]; 28 ll p; 29 30 ///10^5*64 31 void dfs(ll i,ll j,ll k) 32 { 33 if (k==f[p].g+1) 34 { 35 ll l,z; 36 y[j][0]=0; 37 x[j]=i; 38 z=f[p].g; 39 for (l=1;l<=i;l++) 40 { 41 for (k=1;k<=z;k++) 42 if (l%zhi[f[p].a[k]]==0 && use[k]) 43 break; 44 if (k==z+1) 45 y[j][l]=y[j][l-1]+1; 46 else 47 y[j][l]=y[j][l-1]; 48 } 49 gx[j]=y[j][i]; 50 return; 51 } 52 use[k]=0; 53 dfs(i,j*2,k+1); 54 use[k]=1; 55 dfs(i*zhi[f[p].a[k]],j*2+1,k+1); 56 } 57 58 ll work(ll u,ll v) 59 { 60 ll r=0,i,j; 61 v/=u; 62 63 i=1,j=1; 64 while (i<=f[u].g && j<=f[p].g) 65 { 66 if (f[u].a[i]==f[p].a[j]) 67 { 68 if (f[u].b[i]==f[p].b[j]) 69 r=r*2; 70 else 71 r=r*2+1; 72 i++; 73 j++; 74 } 75 else if (f[u].a[i]>f[p].a[j]) 76 i++; 77 else 78 { 79 j++; 80 r=r*2+1; 81 } 82 } 83 while (j<=f[p].g) 84 r=r*2+1,j++; 85 86 return v/x[r]*gx[r]+y[r][v%x[r]]; 87 } 88 89 int main() 90 { 91 ll t,i,j,k,maxv=1e5; 92 ll n,m,sum; 93 for (i=2;i<=maxv;i++) 94 { 95 if (!vis[i]) 96 { 97 zhi[++zhi_cnt]=i; 98 f[i].g=1; 99 f[i].a[1]=zhi_cnt;100 f[i].b[1]=1;101 }102 for (j=1;j<=zhi_cnt;j++)103 {104 k=i*zhi[j];105 if (k>maxv)106 break;107 vis[k]=1;108 f[k]=f[i];109 if (f[i].a[f[i].g]==j)110 f[k].b[f[k].g]++;111 else112 {113 f[k].g++;114 f[k].a[f[k].g]=j;115 f[k].b[f[k].g]=1;116 }117 if (i%zhi[j]==0)118 break;119 }120 }121 122 scanf("%lld",&t);123 while (t--)124 {125 scanf("%lld%lld%lld",&n,&m,&p);126 // if (p==1)127 // {128 // printf("%lld\n",n*m);129 // continue;130 // }131 dfs(1,0,1);132 133 sum=0;134 for (i=1;i<=p;i++)135 if (p%i==0)136 {137 j=p/i;138 139 sum+=work(i,n)*(m/j);140 }141 printf("%lld\n",sum);142 }143 return 0;144 }145 /*146 5147 1000000000 1000000000 1148 1000000000 1000000000 2149 1000000000 1000000000 10150 100000000 100000000 2151 10 20 15152 1000000000 1000000000 30030153 100000000 100000000 30030154 155 1156 9 9 9157 1158 6 6 12159 160 1161 20 20 11162 163 1164 10 10 6165 */
场上感觉,然后看了题解,以下想法基本是错的……
C.
a1,b1,c1
a2,b2,c2
要求
a1<b2<c1
a2<b1<c2
有可能要按照某种方式排序
两组条件,两者互相约束。
然后就不会做了……
题解:
取反求,变成i能赢j的条件,此时的条件可求。
然后就是偏序的子问题。
不同数组元素的比较,其实还是比较,二维偏序。
cj<bi bj<ai
改为
c,b;b,a数组 为 同一个数组(表示的符号相同)表示即可。
D.
一开始以为是图,觉得不可做,
后面发现是树。。。
点分治
结合题解想了一想,也许可以???
也许可以分为内部处理的 和 通过子根相连的
处理^k(k<=13)
各种多项式操作。 (题解:二项式定理)
看群里说对于k较小的情况,有更好的做法,cf的某些题???
题解:树形DP。
树本身的结构已经提供了层次感???
lca为当前根。
未证实正确的想法:
E.
末尾有0的操作。
只可能为
a->b->c->b->c
b->c->b->c
处理每个区间的最小/最大值
每次a->b时进行修改,
提前记录,也许要额外建一棵树,
数目不多。
题解的方法,特别是最后一部分没看懂。。。
F.
跟E一样,怎么都是各种修改。
没想法,估计较难。