原题 LG-P4005 小 Y 和地铁。
找一下性质,发现对于只有一个交点的站点一定无贡献,对于有且仅有两个交点的考虑发现其有效状态只有四种(即发现对于从线段的左端点与右端点绕过是等效的),于是考虑随机一个初始状态后
原题 SP422 TRANSP2 - Transposing is Even More Fun。
双倍经验 SP419 TRANSP - Transposing is Fun。
挺长时间以前写的题解:
一道很好的群论题,尤其是其中转化的思想还是很高妙的。
不难发现,我们考虑按序为矩阵标号,从
这个东西朴素的交换次数是
由题面中
于是我们想到,若将二进制数抽象为长度为
这时就存在一个很人类智慧的转化,我们可以容易想到每
用经典的莫反思想推导:
可以通过精细实现达到
加强版:
有点不太理解这道题的意义,完全就是更卡常一点,需要更加精细实现,本质没有任何变化。。
推导部分完全相同,最终式子:
发现对于 dfs
跑一下,同时处理
Upd:一种新的思路:
考虑将二进制数抽象为长度为
考虑套用一下 Polya,对于旋转
然后进行一些转化:
接下来的步骤则与之前相同。
原题 LOJ #6672. 「XXOI 2019」惠和惠惠和惠惠惠。
大概是我目前做过所有题里最有意思的了。(推逝式子多有意思)
puts("0")
的。
问题可抽象为在平面直角坐标系中从
考虑 DP,设状态
显然有:
对于
令默慈金数为
从圆上画弦很好理解,从本题理解略有困难,大概是钦定一个从
以上似乎就是个
容易发现其生成函数为:
解个一元二次方程将
继续考虑用
此时对于
再往下就有各种各样的做法了,这里简单提几个并丢一下链接。
首先直接
对于一个
还可以考虑通过某些方式获取结论发现
然后是一些可能用到的资料:
LOJ #6672. 「XXOI 2019」惠和惠惠和惠惠惠(生成函数,整式递推)
xxxxxxxxxx
1441
2
3
4
5
6
7
8
9
10
11
12using namespace std;
13
14mt19937 rnd(random_device{}());
15int rndd(int l, int r){return rnd() % (r - l + 1) + l;}
16bool rnddd(int x){return rndd(1, 100) <= x;}
17
18typedef unsigned int uint;
19typedef unsigned long long unll;
20typedef long long ll;
21typedef long double ld;
22
23
24
25template < typename T = int >
26inline T read(void);
27
28int N;
29int pos[50];
30int status[50];
31bool itsc[50][50];
32int cur(0);
33int ans(INT_MAX);
34struct Line{int l, r;};
35basic_string < Line > lines;
36
37int main(){
38 freopen("corruption.in", "r", stdin);
39 freopen("corruption.out", "w", stdout);
40 auto notIntersect = [](int a, int b)->bool{
41 if(line(a).l > line(b).l)swap(a, b);
42 switch(status[a]){
43 case 1:{
44 switch(status[b]){
45 case 1: return line(a).r < line(b).l || line(b).r < line(a).r;
46 case 2: return true;
47 case 3: return line(b).l > line(a).r;
48 case 4: return line(b).r > line(a).r;
49 }break;
50 }
51 case 2:{
52 switch(status[b]){
53 case 1: return true;
54 case 2: return line(a).r < line(b).l || line(b).r < line(a).r;
55 case 3: return line(b).r > line(a).r;
56 case 4: return line(b).l > line(a).r;
57 }break;
58 }
59 case 3:{
60 switch(status[b]){
61 case 1: return true;
62 case 2: return line(b).r < line(a).r || line(b).l > line(a).r;
63 case 3: return line(b).r > line(a).r;
64 case 4: return line(b).l > line(a).r;
65 }break;
66 }
67 case 4:{
68 switch(status[b]){
69 case 1: return line(b).r < line(a).r || line(b).l > line(a).r;
70 case 2: return true;
71 case 3: return line(b).l > line(a).r;
72 case 4: return line(b).r > line(a).r;
73 }break;
74 }
75 }return false;
76 };
77 auto Intersect = [notIntersect](int i, int j)->bool{return !notIntersect(i, j);};//判断写反了,懒的改就写了个 notIntersect 转一下。。。。。。
78 auto SetOrigin = [Intersect](void)->void{
79 cur = 0;
80 for(int i = 1; i <= N; ++i)for(int j = i + 1; j <= N; ++j)cur += (itsc[i][j] = itsc[j][i] = Intersect(i, j));//, printf("checking i = %d, j = %d, res = %d\n", i, j, itsc[i][j] ? 1 : 0);
81 ans = min(ans, cur);
82 };
83 auto Anneal = [Intersect](void)->void{
84 double T = 50.0, delta = 0.993;
85 while(T > 1e-2){
86 int idx = rndd(1, N);
87 int val = rndd(1, 4);
88 while(val == status[idx])val = rndd(1, 4);
89 int nxt = cur;
90 int lsts = status[idx]; status[idx] = val;
91 for(int i = 1; i <= N; ++i)if(i != idx){
92 if(itsc[idx][i] && !Intersect(idx, i))--nxt;
93 else if(!itsc[idx][i] && Intersect(idx, i))++nxt;
94 }
95 if(nxt < cur || exp(-(double)(nxt - cur) / T) > (double)rndd(1, 114514) / 114514){
96 cur = nxt;
97 ans = min(ans, cur);
98 for(int i = 1; i <= N; ++i)if(i != idx)itsc[idx][i] = itsc[i][idx] = Intersect(idx, i);
99 }else status[idx] = lsts;
100 T *= delta;
101 }
102 };
103 int T = read();
104 while(T--){
105 memset(pos, 0, sizeof pos);
106 memset(status, 0, sizeof status);
107 lines.clear();
108 ans = INT_MAX;
109 N = read();
110 for(int i = 1; i <= N; ++i){
111 int val = read();
112 if(pos[val])lines += Line{min(pos[val], i), max(pos[val], i)};
113 else pos[val] = i;
114 }N = lines.size();
115 if(!N){printf("0\n"); continue;}
116 int t = 30;
117 while(t--){
118 memset(itsc, 0, sizeof itsc);
119 for(int i = 1; i <= N; ++i)status[i] = rndd(1, 4);
120 // for(int i = 1; i <= N; ++i)printf("%d ", status[i]);
121 // printf("\n");
122 SetOrigin();
123 Anneal();
124 }printf("%d\n", ans);
125 }
126 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
127 return 0;
128}
129
130template < typename T >
131inline T read(void){
132 T ret(0);
133 int flag(1);
134 char c = getchar();
135 while(c != '-' && !isdigit(c))c = getchar();
136 if(c == '-')flag = -1, c = getchar();
137 while(isdigit(c)){
138 ret *= 10;
139 ret += int(c - '0');
140 c = getchar();
141 }
142 ret *= flag;
143 return ret;
144}
xxxxxxxxxx
1041
2
3
4
5
6
7
8
9
10
11
12using namespace std;
13
14mt19937 rnd(random_device{}());
15int rndd(int l, int r){return rnd() % (r - l + 1) + l;}
16bool rnddd(int x){return rndd(1, 100) <= x;}
17
18typedef unsigned int uint;
19typedef unsigned long long unll;
20typedef long long ll;
21typedef long double ld;
22
23
24
25
26template < typename T = int >
27inline T read(void);
28
29int A, B;
30int N, gcdv;
31ll ans(0);
32ll pow2[LIMIT + 100];
33basic_string < int > Prime;
34bitset < LIMIT + 100 > notPrime;
35struct Num{int v; int cnt;};
36basic_string < Num > fact;
37
38ll qpow(ll a, ll b){
39 ll ret(1), mul(a);
40 while(b){
41 if(b & 1)ret = ret * mul % MOD;
42 b >>= 1;
43 mul = mul * mul % MOD;
44 }return ret;
45}
46void Init(int x){
47 fact.clear();
48 for(auto p : Prime){
49 if(p * p > x)break;
50 if(x % p == 0)fact += {p, 0};
51 while(x % p == 0)fact.back().cnt++, x /= p;
52 }if(x != 1)fact += {x, 1};
53}
54void dfs(int dep = 0, ll d = 1, ll base = 1, ll div = 1){
55 if(dep == (int)fact.size())
56 return (ans += pow2[gcdv * (N / d)] * (d / div * base) % MOD) %= MOD, void();
57 dfs(dep + 1, d, base, div);
58 base *= (fact.at(dep).v - 1), div *= fact.at(dep).v;
59 for(int i = 1; i <= fact.at(dep).cnt; ++i)
60 d *= fact.at(dep).v, dfs(dep + 1, d, base, div);
61}
62
63int main(){
64 freopen("transposition.in", "r", stdin);
65 freopen("transposition.out", "w", stdout);
66 for(int i = 2; i <= LIMIT; ++i){
67 if(!notPrime[i])Prime += i;
68 for(auto p : Prime){
69 if(p * i > LIMIT)break;
70 notPrime[p * i] = true;
71 if(i % p == 0)break;
72 }
73 }
74 pow2[0] = 1;
75 for(int i = 1; i <= LIMIT; ++i)pow2[i] = pow2[i - 1] * 2 % MOD;
76 int T = read();
77 while(T--){
78 A = read(), B = read();
79 N = (A + B) / __gcd(A, B), gcdv = __gcd(A, B);
80 Init(N);
81 ans = 0;
82 dfs();
83 (ans *= qpow(N, MOD - 2)) %= MOD;
84 printf("%lld\n", (pow2[A + B] - ans + MOD) % MOD);
85 }
86 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
87 return 0;
88}
89
90template < typename T >
91inline T read(void){
92 T ret(0);
93 int flag(1);
94 char c = getchar();
95 while(c != '-' && !isdigit(c))c = getchar();
96 if(c == '-')flag = -1, c = getchar();
97 while(isdigit(c)){
98 ret *= 10;
99 ret += int(c - '0');
100 c = getchar();
101 }
102 ret *= flag;
103 return ret;
104}
xxxxxxxxxx
661
2
3
4
5
6
7
8
9
10
11
12using namespace std;
13
14mt19937 rnd(random_device{}());
15int rndd(int l, int r){return rnd() % (r - l + 1) + l;}
16bool rnddd(int x){return rndd(1, 100) <= x;}
17
18typedef unsigned int uint;
19typedef unsigned long long unll;
20typedef long long ll;
21typedef long double ld;
22
23template < typename T = int >
24inline T read(void);
25
26int N, K;
27ll MOD;
28ll dp[11000000];
29ll inv[11000000];
30
31int main(){
32 freopen("slack_off.in", "r", stdin);
33 freopen("slack_off.out", "w", stdout);
34 N = read(), K = read(), MOD = read();
35 if(K > N)printf("0\n"), exit(0);
36 inv[1] = 1;
37 for(int i = 2; i <= N + 100; ++i)inv[i] = (MOD - MOD / i) * inv[MOD % i] % MOD;
38 dp[0] = 1;
39 dp[1] = K - 1;
40 dp[2] = (ll)K * (K - 1) / 2 % MOD;
41 for(int i = 0; i + 3 <= N - K + 1; ++i)
42 dp[i + 3] = (
43 dp[i] * 3 * i % MOD * (i + 1) % MOD +
44 dp[i + 1] * ((5 * i + 3 * K + 6) % MOD) % MOD * (i + 1) % MOD +
45 dp[i + 2] * (i + K + 1) % MOD * (i + K + 2) % MOD
46 ) % MOD * inv[i + 3] % MOD * inv[i + K + 2] % MOD;
47 printf("%lld\n", dp[N - K + 1]);
48 fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
49 return 0;
50}
51
52template < typename T >
53inline T read(void){
54 T ret(0);
55 int flag(1);
56 char c = getchar();
57 while(c != '-' && !isdigit(c))c = getchar();
58 if(c == '-')flag = -1, c = getchar();
59 while(isdigit(c)){
60 ret *= 10;
61 ret += int(c - '0');
62 c = getchar();
63 }
64 ret *= flag;
65 return ret;
66}